mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-02-07 02:40:30 -05:00
[Feature] Entrance Rando v2 (#2071)
This commit is contained in:
parent
598cac725e
commit
d9f3844b2d
@ -261,6 +261,12 @@ typedef struct {
|
|||||||
/* */ char adultAltarText[750];
|
/* */ char adultAltarText[750];
|
||||||
/* */ char ganonHintText[150];
|
/* */ char ganonHintText[150];
|
||||||
/* */ char ganonText[250];
|
/* */ char ganonText[250];
|
||||||
|
/* */ char warpMinuetText[100];
|
||||||
|
/* */ char warpBoleroText[100];
|
||||||
|
/* */ char warpSerenadeText[100];
|
||||||
|
/* */ char warpRequiemText[100];
|
||||||
|
/* */ char warpNocturneText[100];
|
||||||
|
/* */ char warpPreludeText[100];
|
||||||
/* */ u8 seedIcons[5];
|
/* */ u8 seedIcons[5];
|
||||||
/* */ u16 randomizerInf[9];
|
/* */ u16 randomizerInf[9];
|
||||||
/* */ u16 adultTradeItems;
|
/* */ u16 adultTradeItems;
|
||||||
|
@ -28,6 +28,13 @@ typedef enum {
|
|||||||
TEXT_SCRUB_RANDOM_FREE = 0x9001,
|
TEXT_SCRUB_RANDOM_FREE = 0x9001,
|
||||||
TEXT_SHOP_ITEM_RANDOM = 0x9100,
|
TEXT_SHOP_ITEM_RANDOM = 0x9100,
|
||||||
TEXT_SHOP_ITEM_RANDOM_CONFIRM = 0x9101,
|
TEXT_SHOP_ITEM_RANDOM_CONFIRM = 0x9101,
|
||||||
|
TEXT_WARP_MINUET_OF_FOREST = 0x88D,
|
||||||
|
TEXT_WARP_BOLERO_OF_FIRE = 0x88E,
|
||||||
|
TEXT_WARP_SERENADE_OF_WATER = 0x88F,
|
||||||
|
TEXT_WARP_REQUIEM_OF_SPIRIT = 0x890,
|
||||||
|
TEXT_WARP_NOCTURNE_OF_SHADOW = 0x891,
|
||||||
|
TEXT_WARP_PRELUDE_OF_LIGHT = 0x892,
|
||||||
|
TEXT_WARP_RANDOM_REPLACED_TEXT = 0x9200,
|
||||||
} TextIDs;
|
} TextIDs;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -570,6 +570,7 @@ const std::vector<PresetEntry> s6PresetEntries = {
|
|||||||
PRESET_ENTRY_S32("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON),
|
PRESET_ENTRY_S32("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON),
|
||||||
PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_STARTWITH),
|
PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_STARTWITH),
|
||||||
PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1),
|
PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1),
|
||||||
|
PRESET_ENTRY_S32("gRandomizeShuffleOverworldSpawns", RO_GENERIC_ON),
|
||||||
PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1),
|
PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1),
|
||||||
PRESET_ENTRY_S32("gRandomizeSkipChildZelda", 1),
|
PRESET_ENTRY_S32("gRandomizeSkipChildZelda", 1),
|
||||||
PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1),
|
PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1),
|
||||||
@ -674,7 +675,7 @@ const std::map<PresetType, PresetTypeDefinition> presetTypes = {
|
|||||||
{ RANDOMIZER_PRESET_S6, {
|
{ RANDOMIZER_PRESET_S6, {
|
||||||
"S6 Tournament (Adapted)",
|
"S6 Tournament (Adapted)",
|
||||||
"Matches OOTR S6 tournament settings as close as we can get with the options available in SoH. The following differences are notable:\n" \
|
"Matches OOTR S6 tournament settings as close as we can get with the options available in SoH. The following differences are notable:\n" \
|
||||||
"- Child overworld spawn not randomized\n" \
|
"- Both child and adult overworld spawns are randomized" \
|
||||||
"- Dungeon rewards are shuffled at the end of dungeons, rather than at the end of their own dungeon\n" \
|
"- Dungeon rewards are shuffled at the end of dungeons, rather than at the end of their own dungeon\n" \
|
||||||
"- Full adult trade sequence is shuffled instead of the selected 4\n" \
|
"- Full adult trade sequence is shuffled instead of the selected 4\n" \
|
||||||
"- Hint distribution no \"tournament\" mode, falling back to balanced",
|
"- Hint distribution no \"tournament\" mode, falling back to balanced",
|
||||||
|
@ -24,14 +24,22 @@ static int curNumRandomizedEntrances = 0;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
EntranceType type;
|
EntranceType type;
|
||||||
uint32_t parentRegion;
|
AreaKey parentRegion;
|
||||||
uint32_t connectedRegion;
|
AreaKey connectedRegion;
|
||||||
int16_t index;
|
int16_t index;
|
||||||
int16_t blueWarp;
|
int16_t blueWarp;
|
||||||
} EntranceLinkInfo;
|
} EntranceLinkInfo;
|
||||||
|
|
||||||
|
EntranceLinkInfo NO_RETURN_ENTRANCE = {EntranceType::None, NONE, NONE, -1};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
std::list<AreaKey> targetRegions;
|
||||||
|
std::list<EntranceType> allowedTypes;
|
||||||
|
} PriorityEntrance;
|
||||||
//primary, secondary
|
//primary, secondary
|
||||||
using EntranceInfoPair = std::pair<EntranceLinkInfo, EntranceLinkInfo>;
|
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*>>;
|
||||||
|
|
||||||
//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
|
||||||
@ -73,16 +81,12 @@ void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
|
|||||||
forwardEntrance->SetBlueWarp(forwardEntry.blueWarp);
|
forwardEntrance->SetBlueWarp(forwardEntry.blueWarp);
|
||||||
forwardEntrance->SetType(forwardEntry.type);
|
forwardEntrance->SetType(forwardEntry.type);
|
||||||
forwardEntrance->SetAsPrimary();
|
forwardEntrance->SetAsPrimary();
|
||||||
// if type == 'Grotto':
|
|
||||||
// forward_entrance.data['index'] = 0x0700 + forward_entrance.data['grotto_id']
|
|
||||||
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->SetBlueWarp(returnEntry.blueWarp);
|
||||||
returnEntrance->SetType(returnEntry.type);
|
returnEntrance->SetType(returnEntry.type);
|
||||||
forwardEntrance->BindTwoWay(returnEntrance);
|
forwardEntrance->BindTwoWay(returnEntrance);
|
||||||
// if type == 'Grotto':
|
|
||||||
// return_entrance.data['index'] = 0x0800 + return_entrance.data['grotto_id']
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,10 +94,18 @@ void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
|
|||||||
static std::vector<Entrance*> AssumeEntrancePool(std::vector<Entrance*>& entrancePool) {
|
static std::vector<Entrance*> AssumeEntrancePool(std::vector<Entrance*>& entrancePool) {
|
||||||
std::vector<Entrance*> assumedPool = {};
|
std::vector<Entrance*> assumedPool = {};
|
||||||
for (Entrance* entrance : entrancePool) {
|
for (Entrance* entrance : entrancePool) {
|
||||||
|
totalRandomizableEntrances++;
|
||||||
Entrance* assumedForward = entrance->AssumeReachable();
|
Entrance* assumedForward = entrance->AssumeReachable();
|
||||||
if (entrance->GetReverse() != nullptr /*&& entrances are not decoupled*/) {
|
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||||
Entrance* assumedReturn = entrance->GetReverse()->AssumeReachable();
|
Entrance* assumedReturn = entrance->GetReverse()->AssumeReachable();
|
||||||
//mixed pool assumption stuff
|
if (!(Settings::MixedEntrancePools && (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)))) {
|
||||||
|
auto type = entrance->GetType();
|
||||||
|
if (((type == EntranceType::Dungeon || type == EntranceType::GrottoGrave) && entrance->GetReverse()->GetName() != "Spirit Temple Entryway -> Desert Colossus From Spirit Entryway") ||
|
||||||
|
(type == EntranceType::Interior && Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL))) {
|
||||||
|
// In most cases, Dungeon, Grotto/Grave and Simple Interior exits shouldn't be assumed able to give access to their parent region
|
||||||
|
assumedReturn->SetCondition([]{return false;});
|
||||||
|
}
|
||||||
|
}
|
||||||
assumedForward->BindTwoWay(assumedReturn);
|
assumedForward->BindTwoWay(assumedReturn);
|
||||||
}
|
}
|
||||||
assumedPool.push_back(assumedForward);
|
assumedPool.push_back(assumedForward);
|
||||||
@ -101,10 +113,34 @@ static std::vector<Entrance*> AssumeEntrancePool(std::vector<Entrance*>& entranc
|
|||||||
return assumedPool;
|
return assumedPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<Entrance*> BuildOneWayTargets(std::vector<EntranceType> typesToInclude, std::vector<std::pair<AreaKey, AreaKey>> exclude = {}/*, target_region_names*/) {
|
||||||
|
std::vector<Entrance*> oneWayEntrances = {};
|
||||||
|
// Get all entrances of the specified type
|
||||||
|
for (EntranceType poolType : typesToInclude) {
|
||||||
|
AddElementsToPool(oneWayEntrances, GetShuffleableEntrances(poolType, false));
|
||||||
|
}
|
||||||
|
// Filter out any that are passed in the exclusion list
|
||||||
|
FilterAndEraseFromPool(oneWayEntrances, [&exclude](Entrance* entrance){
|
||||||
|
std::pair<AreaKey, AreaKey> entranceBeingChecked (entrance->GetParentRegionKey(), entrance->GetConnectedRegionKey());
|
||||||
|
return ElementInContainer(entranceBeingChecked, exclude);
|
||||||
|
});
|
||||||
|
|
||||||
|
// The code below is part of the function in ootr, but no use of the function ever provides target_region_names
|
||||||
|
// if target_region_names:
|
||||||
|
// return [entrance.get_new_target() for entrance in valid_one_way_entrances
|
||||||
|
// if entrance.connected_region.name in target_region_names]
|
||||||
|
|
||||||
|
std::vector<Entrance*> newTargets = {};
|
||||||
|
for (Entrance* entrance : oneWayEntrances) {
|
||||||
|
newTargets.push_back(entrance->GetNewTarget());
|
||||||
|
}
|
||||||
|
return newTargets;
|
||||||
|
}
|
||||||
|
|
||||||
//returns restrictive entrances and soft entrances in an array of size 2 (restrictive vector is index 0, soft is index 1)
|
//returns restrictive entrances and soft entrances in an array of size 2 (restrictive vector is index 0, soft is index 1)
|
||||||
static std::array<std::vector<Entrance*>, 2> SplitEntrancesByRequirements(std::vector<Entrance*>& entrancesToSplit, std::vector<Entrance*>& assumedEntrances) {
|
static std::array<std::vector<Entrance*>, 2> SplitEntrancesByRequirements(std::vector<Entrance*>& entrancesToSplit, std::vector<Entrance*>& assumedEntrances) {
|
||||||
//First, disconnect all root assumed entrances and save which regions they were originally connected to, so we can reconnect them later
|
//First, disconnect all root assumed entrances and save which regions they were originally connected to, so we can reconnect them later
|
||||||
std::map<Entrance*, uint32_t> originalConnectedRegions = {};
|
std::map<Entrance*, AreaKey> originalConnectedRegions = {};
|
||||||
std::set<Entrance*> entrancesToDisconnect = {};
|
std::set<Entrance*> entrancesToDisconnect = {};
|
||||||
for (Entrance* entrance : assumedEntrances) {
|
for (Entrance* entrance : assumedEntrances) {
|
||||||
entrancesToDisconnect.insert(entrance);
|
entrancesToDisconnect.insert(entrance);
|
||||||
@ -126,9 +162,9 @@ static std::array<std::vector<Entrance*>, 2> SplitEntrancesByRequirements(std::v
|
|||||||
std::vector<Entrance*> softEntrances = {};
|
std::vector<Entrance*> softEntrances = {};
|
||||||
|
|
||||||
Logic::LogicReset();
|
Logic::LogicReset();
|
||||||
// //Apply the effects of all advancement items to search for entrance accessibility
|
// Apply the effects of all advancement items to search for entrance accessibility
|
||||||
std::vector<uint32_t> items = FilterFromPool(ItemPool, [](const auto i){ return ItemTable(i).IsAdvancement();});
|
std::vector<ItemKey> items = FilterFromPool(ItemPool, [](const ItemKey i){ return ItemTable(i).IsAdvancement();});
|
||||||
for (uint32_t unplacedItem : items) {
|
for (ItemKey unplacedItem : items) {
|
||||||
ItemTable(unplacedItem).ApplyEffect();
|
ItemTable(unplacedItem).ApplyEffect();
|
||||||
}
|
}
|
||||||
// run a search to see what's accessible
|
// run a search to see what's accessible
|
||||||
@ -160,7 +196,18 @@ static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::ve
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//one-way entrance stuff
|
// One way entrances shouldn't lead to the same scene as other already chosen one way entrances
|
||||||
|
auto type = entrance->GetType();
|
||||||
|
const std::vector<EntranceType> oneWayTypes = {EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong};
|
||||||
|
if (ElementInContainer(type, oneWayTypes)) {
|
||||||
|
for (auto& rollback : rollbacks) {
|
||||||
|
if (rollback.first->GetConnectedRegion()->scene == target->GetConnectedRegion()->scene) {
|
||||||
|
auto message = "A one way entrance already leads to " + target->to_string() + ". Connection failed.\n";
|
||||||
|
SPDLOG_DEBUG(message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -171,16 +218,18 @@ static void ChangeConnections(Entrance* entrance, Entrance* targetEntrance) {
|
|||||||
SPDLOG_DEBUG(message);
|
SPDLOG_DEBUG(message);
|
||||||
entrance->Connect(targetEntrance->Disconnect());
|
entrance->Connect(targetEntrance->Disconnect());
|
||||||
entrance->SetReplacement(targetEntrance->GetReplacement());
|
entrance->SetReplacement(targetEntrance->GetReplacement());
|
||||||
if (entrance->GetReverse() != nullptr /*&& entrances aren't decoupled*/) {
|
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||||
targetEntrance->GetReplacement()->GetReverse()->Connect(entrance->GetReverse()->GetAssumed()->Disconnect());
|
targetEntrance->GetReplacement()->GetReverse()->Connect(entrance->GetReverse()->GetAssumed()->Disconnect());
|
||||||
targetEntrance->GetReplacement()->GetReverse()->SetReplacement(entrance->GetReverse());
|
targetEntrance->GetReplacement()->GetReverse()->SetReplacement(entrance->GetReverse());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In the event that we need to retry shuffling an entire group we can restore the
|
||||||
|
// original connections to reset the entrance and target entrance.
|
||||||
static void RestoreConnections(Entrance* entrance, Entrance* targetEntrance) {
|
static void RestoreConnections(Entrance* entrance, Entrance* targetEntrance) {
|
||||||
targetEntrance->Connect(entrance->Disconnect());
|
targetEntrance->Connect(entrance->Disconnect());
|
||||||
entrance->SetReplacement(nullptr);
|
entrance->SetReplacement(nullptr);
|
||||||
if (entrance->GetReverse() != nullptr /*&& entrances are not decoupled*/) {
|
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||||
entrance->GetReverse()->GetAssumed()->Connect(targetEntrance->GetReplacement()->GetReverse()->Disconnect());
|
entrance->GetReverse()->GetAssumed()->Connect(targetEntrance->GetReplacement()->GetReverse()->Disconnect());
|
||||||
targetEntrance->GetReplacement()->GetReverse()->SetReplacement(nullptr);
|
targetEntrance->GetReplacement()->GetReverse()->SetReplacement(nullptr);
|
||||||
}
|
}
|
||||||
@ -198,7 +247,7 @@ static void DeleteTargetEntrance(Entrance* targetEntrance) {
|
|||||||
|
|
||||||
static void ConfirmReplacement(Entrance* entrance, Entrance* targetEntrance) {
|
static void ConfirmReplacement(Entrance* entrance, Entrance* targetEntrance) {
|
||||||
DeleteTargetEntrance(targetEntrance);
|
DeleteTargetEntrance(targetEntrance);
|
||||||
if (entrance->GetReverse() != nullptr /*&& entrances are not decoupled*/) {
|
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||||
auto replacedReverse = targetEntrance->GetReplacement()->GetReverse();
|
auto replacedReverse = targetEntrance->GetReplacement()->GetReverse();
|
||||||
DeleteTargetEntrance(replacedReverse->GetReverse()->GetAssumed());
|
DeleteTargetEntrance(replacedReverse->GetReverse()->GetAssumed());
|
||||||
}
|
}
|
||||||
@ -227,12 +276,12 @@ static bool EntranceUnreachableAs(Entrance* entrance, uint8_t age, std::vector<E
|
|||||||
return age == AGE_CHILD;
|
return age == AGE_CHILD;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other entrances such as Interior, Dungeon or Grotto are fine unless they have a parent which is one of the above
|
// Other entrances such as Interior, Dungeon or Grotto are fine unless they have a parent which is one of the above cases
|
||||||
// cases Recursively check parent entrances to verify that they are also not reachable as the wrong age
|
// Recursively check parent entrances to verify that they are also not reachable as the wrong age
|
||||||
auto& parentEntrances = entrance->GetParentRegion()->entrances;
|
auto& parentEntrances = entrance->GetParentRegion()->entrances;
|
||||||
for (Entrance* parentEntrance : parentEntrances) {
|
for (Entrance* parentEntrance : parentEntrances) {
|
||||||
|
|
||||||
// if parentEntrance is in alreadyChecked, then continue
|
//if parentEntrance is in alreadyChecked, then continue
|
||||||
if (ElementInContainer(parentEntrance, alreadyChecked)) {
|
if (ElementInContainer(parentEntrance, alreadyChecked)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -255,16 +304,18 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
|||||||
type = entrancePlaced->GetType();
|
type = entrancePlaced->GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkPoeCollectorAccess = (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)) && (entrancePlaced == nullptr /*|| Settings::MixedEntrancePools.IsNot(MIXEDENTRANCES_OFF)*/ ||
|
bool checkPoeCollectorAccess = (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)) && (entrancePlaced == nullptr || Settings::MixedEntrancePools ||
|
||||||
type == EntranceType::Interior || type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn || type == EntranceType::WarpSong || type == EntranceType::OwlDrop);
|
type == EntranceType::Interior || type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn || type == EntranceType::WarpSong || type == EntranceType::OwlDrop);
|
||||||
bool checkOtherEntranceAccess = (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL) /*|| Settings::ShuffleOverworldSpawns*/) && (entrancePlaced == nullptr /*|| Settings::MixedEntrancePools.IsNot(MIXEDENTRANCES_OFF)*/ ||
|
bool checkOtherEntranceAccess = (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL) || Settings::ShuffleOverworldSpawns) && (entrancePlaced == nullptr || Settings::MixedEntrancePools ||
|
||||||
type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn || type == EntranceType::WarpSong || type == EntranceType::OwlDrop);
|
type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn || type == EntranceType::WarpSong || type == EntranceType::OwlDrop);
|
||||||
|
|
||||||
// Check to make sure all locations are still reachable
|
// Search the world to verify that all necessary conditions are still being held
|
||||||
|
// Conditions will be checked during the search and any that fail will be figured out
|
||||||
|
// afterwards
|
||||||
Logic::LogicReset();
|
Logic::LogicReset();
|
||||||
GetAccessibleLocations({}, SearchMode::ValidateWorld, "", checkPoeCollectorAccess, checkOtherEntranceAccess);
|
GetAccessibleLocations({}, SearchMode::ValidateWorld, "", checkPoeCollectorAccess, checkOtherEntranceAccess);
|
||||||
|
|
||||||
// if not world.decouple_entrances:
|
if (!Settings::DecoupleEntrances) {
|
||||||
// Unless entrances are decoupled, we don't want the player to end up through certain entrances as the wrong age
|
// Unless entrances are decoupled, we don't want the player to end up through certain entrances as the wrong age
|
||||||
// This means we need to hard check that none of the relevant entrances are ever reachable as that age
|
// This means we need to hard check that none of the relevant entrances are ever reachable as that age
|
||||||
// This is mostly relevant when mixing entrance pools or shuffling special interiors (such as windmill or kak potion shop)
|
// This is mostly relevant when mixing entrance pools or shuffling special interiors (such as windmill or kak potion shop)
|
||||||
@ -308,6 +359,7 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Settings::ShuffleInteriorEntrances.IsNot(SHUFFLEINTERIORS_OFF) && Settings::GossipStoneHints.IsNot(HINTS_NO_HINTS) &&
|
if (Settings::ShuffleInteriorEntrances.IsNot(SHUFFLEINTERIORS_OFF) && Settings::GossipStoneHints.IsNot(HINTS_NO_HINTS) &&
|
||||||
(entrancePlaced == nullptr || type == EntranceType::Interior || type == EntranceType::SpecialInterior)) {
|
(entrancePlaced == nullptr || type == EntranceType::Interior || type == EntranceType::SpecialInterior)) {
|
||||||
@ -373,7 +425,7 @@ static bool ReplaceEntrance(Entrance* entrance, Entrance* target, std::vector<En
|
|||||||
#ifdef ENABLE_DEBUG
|
#ifdef ENABLE_DEBUG
|
||||||
std::string ticks = std::to_string(svcGetSystemTick());
|
std::string ticks = std::to_string(svcGetSystemTick());
|
||||||
auto message = "Dumping World Graph at " + ticks + "\n";
|
auto message = "Dumping World Graph at " + ticks + "\n";
|
||||||
//PlacementLog_Msg(message);
|
//SPDLOG_DEBUG(message);
|
||||||
//Areas::DumpWorldGraph(ticks);
|
//Areas::DumpWorldGraph(ticks);
|
||||||
#endif
|
#endif
|
||||||
rollbacks.push_back(EntrancePair{entrance, target});
|
rollbacks.push_back(EntrancePair{entrance, target});
|
||||||
@ -384,7 +436,7 @@ static bool ReplaceEntrance(Entrance* entrance, Entrance* target, std::vector<En
|
|||||||
#ifdef ENABLE_DEBUG
|
#ifdef ENABLE_DEBUG
|
||||||
std::string ticks = std::to_string(svcGetSystemTick());
|
std::string ticks = std::to_string(svcGetSystemTick());
|
||||||
auto message = "Dumping World Graph at " + ticks + "\n";
|
auto message = "Dumping World Graph at " + ticks + "\n";
|
||||||
//PlacementLog_Msg(message);
|
//SPDLOG_DEBUG(message);
|
||||||
//Areas::DumpWorldGraph(ticks);
|
//Areas::DumpWorldGraph(ticks);
|
||||||
#endif
|
#endif
|
||||||
if (entrance->GetConnectedRegionKey() != NONE) {
|
if (entrance->GetConnectedRegionKey() != NONE) {
|
||||||
@ -395,6 +447,84 @@ static bool ReplaceEntrance(Entrance* entrance, Entrance* target, std::vector<En
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Connect one random entrance from entrance pools to one random target in the respective target pool.
|
||||||
|
// Entrance chosen will have one of the allowed types.
|
||||||
|
// Target chosen will lead to one of the allowed regions.
|
||||||
|
static bool PlaceOneWayPriorityEntrance(std::string priorityName, std::list<AreaKey>& allowedRegions, std::list<EntranceType>& allowedTypes, std::vector<EntrancePair>& rollbacks, EntrancePools oneWayEntrancePools, EntrancePools oneWayTargetEntrancePools) {
|
||||||
|
// Combine the entrances for allowed types in one list.
|
||||||
|
// Shuffle this list.
|
||||||
|
// Pick the first one not already set, not adult spawn, that has a valid target entrance.
|
||||||
|
// Assemble then clear entrances from the pool and target pools as appropriate.
|
||||||
|
std::vector<Entrance*> availPool = {};
|
||||||
|
for (auto& pool : oneWayEntrancePools) {
|
||||||
|
auto entranceType = pool.first;
|
||||||
|
if (ElementInContainer(entranceType, allowedTypes)) {
|
||||||
|
AddElementsToPool(availPool, pool.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Shuffle(availPool);
|
||||||
|
|
||||||
|
for (Entrance* entrance : availPool) {
|
||||||
|
if (entrance->GetReplacement() != nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Only allow Adult Spawn as sole Nocturne access if hints != mask.
|
||||||
|
// Otherwise, child access is required here (adult access assumed or guaranteed later).
|
||||||
|
if (entrance->GetParentRegionKey() == ADULT_SPAWN) {
|
||||||
|
if (priorityName != "Nocturne" || Settings::GossipStoneHints.Is(HINTS_MASK_OF_TRUTH)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If not shuffling dungeons, Nocturne requires adult access
|
||||||
|
if (!Settings::ShuffleDungeonEntrances && priorityName == "Nocturne") {
|
||||||
|
if (entrance->GetType() != EntranceType::WarpSong && entrance->GetParentRegionKey() != ADULT_SPAWN) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Entrance* target : oneWayTargetEntrancePools[entrance->GetType()]) {
|
||||||
|
AreaKey targetRegionKey = target->GetConnectedRegionKey();
|
||||||
|
if (targetRegionKey != NONE && ElementInContainer(targetRegionKey, allowedRegions)) {
|
||||||
|
if (ReplaceEntrance(entrance, target, rollbacks)) {
|
||||||
|
// Return once the entrance has been replaced
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef ENABLE_DEBUG
|
||||||
|
auto message = "ERROR: Unable to place priority one-way entrance for " + priorityName + "\n";
|
||||||
|
SPDLOG_DEBUG(message);
|
||||||
|
PlacementLog_Write();
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the first entrance to Impas House has been placed, try to place the next one immediately to reduce chances of failure.
|
||||||
|
static bool PlaceOtherImpasHouseEntrance(std::vector<Entrance*> entrances, std::vector<Entrance*> targetEntrances, std::vector<EntrancePair>& rollbacks) {
|
||||||
|
// Get the other impas house entrance
|
||||||
|
auto otherImpaTargets = FilterFromPool(targetEntrances, [](const Entrance* target){return (target->GetConnectedRegionKey() == KAK_IMPAS_HOUSE || target->GetConnectedRegionKey() == KAK_IMPAS_HOUSE_BACK);});
|
||||||
|
if (otherImpaTargets.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entrance* otherImpaTarget = otherImpaTargets[0];
|
||||||
|
auto m = "Now Placing Other Impa Target: " + otherImpaTarget->GetName() + "\n";
|
||||||
|
SPDLOG_DEBUG(m);
|
||||||
|
AreaKey otherImpaRegion = otherImpaTarget->GetConnectedRegionKey() != KAK_IMPAS_HOUSE_BACK ? KAK_IMPAS_HOUSE_BACK : KAK_IMPAS_HOUSE;
|
||||||
|
for (Entrance* entrance : entrances) {
|
||||||
|
// If the entrance is already connected or it doesn't have the same hint region as the already placed impas house entrance, then don't try to use it
|
||||||
|
if (entrance->GetConnectedRegionKey() != NONE || (GetHintRegionHintKey(otherImpaRegion) != GetHintRegionHintKey(entrance->GetParentRegionKey()))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// If the placement succeeds, we return true
|
||||||
|
if (ReplaceEntrance(entrance, otherImpaTarget, rollbacks)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SPDLOG_DEBUG("No available entrances for placing other impa region.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Shuffle entrances by placing them instead of entrances in the provided target entrances list
|
// Shuffle entrances by placing them instead of entrances in the provided target entrances list
|
||||||
static bool ShuffleEntrances(std::vector<Entrance*>& entrances, std::vector<Entrance*>& targetEntrances, std::vector<EntrancePair>& rollbacks) {
|
static bool ShuffleEntrances(std::vector<Entrance*>& entrances, std::vector<Entrance*>& targetEntrances, std::vector<EntrancePair>& rollbacks) {
|
||||||
|
|
||||||
@ -412,7 +542,17 @@ static bool ShuffleEntrances(std::vector<Entrance*>& entrances, std::vector<Entr
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store whether or not we're about to attempt placing an entrance to Impas House
|
||||||
|
bool attemptedImpasHousePlacement = (target->GetConnectedRegionKey() == KAK_IMPAS_HOUSE || target->GetConnectedRegionKey() == KAK_IMPAS_HOUSE_BACK);
|
||||||
|
|
||||||
if (ReplaceEntrance(entrance, target, rollbacks)) {
|
if (ReplaceEntrance(entrance, target, rollbacks)) {
|
||||||
|
// If shuffle cows is enabled and the last entrance was one to Impas House,
|
||||||
|
// then immediately attempt to place the other entrance to Impas House
|
||||||
|
if (Settings::ShuffleCows && attemptedImpasHousePlacement) {
|
||||||
|
if (!PlaceOtherImpasHouseEntrance(entrances, targetEntrances, rollbacks)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,7 +566,43 @@ static bool ShuffleEntrances(std::vector<Entrance*>& entrances, std::vector<Entr
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ShuffleEntrancePool(std::vector<Entrance*>& entrancePool, std::vector<Entrance*>& targetEntrances) {
|
static bool ShuffleOneWayPriorityEntrances(std::map<std::string, PriorityEntrance>& oneWayPriorities, EntrancePools oneWayEntrancePools, EntrancePools oneWayTargetEntrancePools, int retryCount = 2) {
|
||||||
|
while (retryCount > 0) {
|
||||||
|
retryCount--;
|
||||||
|
std::vector<EntrancePair> rollbacks = {};
|
||||||
|
|
||||||
|
bool success = true;
|
||||||
|
for (auto& priority : oneWayPriorities) {
|
||||||
|
std::string key = priority.first;
|
||||||
|
auto& regions = priority.second.targetRegions;
|
||||||
|
auto& types = priority.second.allowedTypes;
|
||||||
|
success = PlaceOneWayPriorityEntrance(key, regions, types, rollbacks, oneWayEntrancePools, oneWayTargetEntrancePools);
|
||||||
|
if (!success) {
|
||||||
|
for (auto& pair : rollbacks) {
|
||||||
|
RestoreConnections(pair.first, pair.second);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// If there are no issues, log the connections and continue
|
||||||
|
for (auto& pair : rollbacks) {
|
||||||
|
ConfirmReplacement(pair.first, pair.second);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retryCount <= 0) {
|
||||||
|
SPDLOG_DEBUG("Entrance placement attempt count for one way priorities exceeded. Restarting randomization completely\n");
|
||||||
|
entranceShuffleFailure = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShuffleEntrancePool(std::vector<Entrance*>& entrancePool, std::vector<Entrance*>& targetEntrances, int retryCount = 20) {
|
||||||
noRandomEntrances = false;
|
noRandomEntrances = false;
|
||||||
|
|
||||||
auto splitEntrances = SplitEntrancesByRequirements(entrancePool, targetEntrances);
|
auto splitEntrances = SplitEntrancesByRequirements(entrancePool, targetEntrances);
|
||||||
@ -434,14 +610,14 @@ static void ShuffleEntrancePool(std::vector<Entrance*>& entrancePool, std::vecto
|
|||||||
auto& restrictiveEntrances = splitEntrances[0];
|
auto& restrictiveEntrances = splitEntrances[0];
|
||||||
auto& softEntrances = splitEntrances[1];
|
auto& softEntrances = splitEntrances[1];
|
||||||
|
|
||||||
int retries = 20;
|
int retries = retryCount;
|
||||||
while (retries > 0) {
|
while (retries > 0) {
|
||||||
if (retries != 20) {
|
if (retries != retryCount) {
|
||||||
#ifdef ENABLE_DEBUG
|
#ifdef ENABLE_DEBUG
|
||||||
std::string ticks = std::to_string(svcGetSystemTick());
|
std::string ticks = std::to_string(svcGetSystemTick());
|
||||||
auto message = "Failed to connect entrances. Retrying " + std::to_string(retries) + " more times.\nDumping World Graph at " + ticks + "\n";
|
auto message = "Failed to connect entrances. Retrying " + std::to_string(retries) + " more times.\nDumping World Graph at " + ticks + "\n";
|
||||||
PlacementLog_Msg(message);
|
SPDLOG_DEBUG(message);
|
||||||
Areas::DumpWorldGraph(ticks);
|
//Areas::DumpWorldGraph(ticks);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
retries--;
|
retries--;
|
||||||
@ -481,6 +657,17 @@ static void ShuffleEntrancePool(std::vector<Entrance*>& entrancePool, std::vecto
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetShuffledEntrances(EntrancePools entrancePools) {
|
||||||
|
for (auto& pool : entrancePools) {
|
||||||
|
for (Entrance* entrance : pool.second) {
|
||||||
|
entrance->SetAsShuffled();
|
||||||
|
if (entrance->GetReverse() != nullptr) {
|
||||||
|
entrance->GetReverse()->SetAsShuffled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Process for setting up the shuffling of all entrances to be shuffled
|
//Process for setting up the shuffling of all entrances to be shuffled
|
||||||
int ShuffleAllEntrances() {
|
int ShuffleAllEntrances() {
|
||||||
|
|
||||||
@ -502,7 +689,7 @@ int ShuffleAllEntrances() {
|
|||||||
{{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, 0x060C}},
|
||||||
{{EntranceType::Dungeon, DESERT_COLOSSUS, SPIRIT_TEMPLE_ENTRYWAY, 0x0082},
|
{{EntranceType::Dungeon, DESERT_COLOSSUS, SPIRIT_TEMPLE_ENTRYWAY, 0x0082},
|
||||||
{EntranceType::Dungeon, SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS, 0x01E1, 0x0610}},
|
{EntranceType::Dungeon, SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, 0x01E1, 0x0610}},
|
||||||
{{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, 0x0580}},
|
||||||
{{EntranceType::Dungeon, KAKARIKO_VILLAGE, BOTTOM_OF_THE_WELL_ENTRYWAY, 0x0098},
|
{{EntranceType::Dungeon, KAKARIKO_VILLAGE, BOTTOM_OF_THE_WELL_ENTRYWAY, 0x0098},
|
||||||
@ -731,20 +918,58 @@ int ShuffleAllEntrances() {
|
|||||||
{EntranceType::Overworld, ZORAS_DOMAIN, ZR_BEHIND_WATERFALL, 0x019D}},
|
{EntranceType::Overworld, ZORAS_DOMAIN, ZR_BEHIND_WATERFALL, 0x019D}},
|
||||||
{{EntranceType::Overworld, ZD_BEHIND_KING_ZORA, ZORAS_FOUNTAIN, 0x0225},
|
{{EntranceType::Overworld, ZD_BEHIND_KING_ZORA, ZORAS_FOUNTAIN, 0x0225},
|
||||||
{EntranceType::Overworld, ZORAS_FOUNTAIN, ZD_BEHIND_KING_ZORA, 0x01A1}},
|
{EntranceType::Overworld, ZORAS_FOUNTAIN, ZD_BEHIND_KING_ZORA, 0x01A1}},
|
||||||
|
|
||||||
|
{{EntranceType::Overworld, GV_LOWER_STREAM, LAKE_HYLIA, 0x0219}, NO_RETURN_ENTRANCE},
|
||||||
|
|
||||||
|
{{EntranceType::OwlDrop, LH_OWL_FLIGHT, HYRULE_FIELD, 0x027E}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::OwlDrop, DMT_OWL_FLIGHT, KAK_IMPAS_ROOFTOP, 0x0554}, NO_RETURN_ENTRANCE},
|
||||||
|
|
||||||
|
{{EntranceType::Spawn, CHILD_SPAWN, KF_LINKS_HOUSE, 0x00BB}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::Spawn, ADULT_SPAWN, TEMPLE_OF_TIME, 0x0282}, NO_RETURN_ENTRANCE}, // 0x282 is an unused entrance index repurposed to differentiate between
|
||||||
|
// Adult Spawn and prelude of light (normally they both use 0x5F4)
|
||||||
|
{{EntranceType::WarpSong, MINUET_OF_FOREST_WARP, SACRED_FOREST_MEADOW, 0x0600}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::WarpSong, BOLERO_OF_FIRE_WARP, DMC_CENTRAL_LOCAL, 0x04F6}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::WarpSong, SERENADE_OF_WATER_WARP, LAKE_HYLIA, 0x0604}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::WarpSong, REQUIEM_OF_SPIRIT_WARP, DESERT_COLOSSUS, 0x01F1}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::WarpSong, NOCTURNE_OF_SHADOW_WARP, GRAVEYARD_WARP_PAD_REGION, 0x0568}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::WarpSong, PRELUDE_OF_LIGHT_WARP, TEMPLE_OF_TIME, 0x05F4}, NO_RETURN_ENTRANCE},
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<std::string, PriorityEntrance> priorityEntranceTable = {
|
||||||
|
{"Bolero", {{DMC_CENTRAL_LOCAL}, {EntranceType::OwlDrop, EntranceType::WarpSong}}},
|
||||||
|
{"Nocturne", {{GRAVEYARD_WARP_PAD_REGION}, {EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong}}},
|
||||||
|
{"Requiem", {{DESERT_COLOSSUS, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY}, {EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong}}},
|
||||||
};
|
};
|
||||||
|
|
||||||
entranceShuffleFailure = false;
|
entranceShuffleFailure = false;
|
||||||
SetAllEntrancesData(entranceShuffleTable);
|
SetAllEntrancesData(entranceShuffleTable);
|
||||||
|
|
||||||
// one_way_entrance_pools = OrderedDict()
|
EntrancePools oneWayEntrancePools = {};
|
||||||
std::map<EntranceType, std::vector<Entrance*>> entrancePools = {};
|
EntrancePools entrancePools = {};
|
||||||
// one_way_priorities = {}
|
std::map<std::string, PriorityEntrance> oneWayPriorities = {};
|
||||||
|
|
||||||
//owl drops
|
// Owl Drops
|
||||||
|
if (Settings::ShuffleOwlDrops) {
|
||||||
|
oneWayEntrancePools[EntranceType::OwlDrop] = GetShuffleableEntrances(EntranceType::OwlDrop);
|
||||||
|
}
|
||||||
|
|
||||||
//spawns
|
// Spawns
|
||||||
|
if (Settings::ShuffleOverworldSpawns) {
|
||||||
|
oneWayEntrancePools[EntranceType::Spawn] = GetShuffleableEntrances(EntranceType::Spawn);
|
||||||
|
}
|
||||||
|
|
||||||
//warpsongs
|
// Warpsongs
|
||||||
|
if (Settings::ShuffleWarpSongs) {
|
||||||
|
oneWayEntrancePools[EntranceType::WarpSong] = GetShuffleableEntrances(EntranceType::WarpSong);
|
||||||
|
// In Glitchless, there aren't any other ways to access these areas
|
||||||
|
if (Settings::Logic.Is(LOGIC_GLITCHLESS)) {
|
||||||
|
oneWayPriorities["Bolero"] = priorityEntranceTable["Bolero"];
|
||||||
|
oneWayPriorities["Nocturne"] = priorityEntranceTable["Nocturne"];
|
||||||
|
if (!Settings::ShuffleDungeonEntrances && !Settings::ShuffleOverworldEntrances) {
|
||||||
|
oneWayPriorities["Requiem"] = priorityEntranceTable["Requiem"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Shuffle Dungeon Entrances
|
//Shuffle Dungeon Entrances
|
||||||
if (Settings::ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) {
|
if (Settings::ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) {
|
||||||
@ -758,57 +983,135 @@ int ShuffleAllEntrances() {
|
|||||||
FilterAndEraseFromPool(entrancePools[EntranceType::Dungeon], [](const Entrance* entrance){return entrance->GetParentRegionKey() == KF_OUTSIDE_DEKU_TREE &&
|
FilterAndEraseFromPool(entrancePools[EntranceType::Dungeon], [](const Entrance* entrance){return entrance->GetParentRegionKey() == KF_OUTSIDE_DEKU_TREE &&
|
||||||
entrance->GetConnectedRegionKey() == DEKU_TREE_ENTRYWAY;});
|
entrance->GetConnectedRegionKey() == DEKU_TREE_ENTRYWAY;});
|
||||||
}
|
}
|
||||||
|
if (Settings::DecoupleEntrances) {
|
||||||
//decoupled entrances stuff
|
for (Entrance* entrance : entrancePools[EntranceType::Dungeon]) {
|
||||||
|
entrancePools[EntranceType::DungeonReverse].push_back(entrance->GetReverse());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//interior entrances
|
// Interior entrances
|
||||||
if (Settings::ShuffleInteriorEntrances.IsNot(SHUFFLEINTERIORS_OFF)) {
|
if (Settings::ShuffleInteriorEntrances.IsNot(SHUFFLEINTERIORS_OFF)) {
|
||||||
entrancePools[EntranceType::Interior] = GetShuffleableEntrances(EntranceType::Interior);
|
entrancePools[EntranceType::Interior] = GetShuffleableEntrances(EntranceType::Interior);
|
||||||
//special interiors
|
// Special interiors
|
||||||
if (Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)) {
|
if (Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)) {
|
||||||
AddElementsToPool(entrancePools[EntranceType::Interior], GetShuffleableEntrances(EntranceType::SpecialInterior));
|
AddElementsToPool(entrancePools[EntranceType::Interior], GetShuffleableEntrances(EntranceType::SpecialInterior));
|
||||||
}
|
}
|
||||||
|
if (Settings::DecoupleEntrances) {
|
||||||
//decoupled entrance stuff
|
for (Entrance* entrance : entrancePools[EntranceType::Interior]) {
|
||||||
|
entrancePools[EntranceType::InteriorReverse].push_back(entrance->GetReverse());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//grotto entrances
|
//grotto entrances
|
||||||
if (Settings::ShuffleGrottoEntrances) {
|
if (Settings::ShuffleGrottoEntrances) {
|
||||||
entrancePools[EntranceType::GrottoGrave] = GetShuffleableEntrances(EntranceType::GrottoGrave);
|
entrancePools[EntranceType::GrottoGrave] = GetShuffleableEntrances(EntranceType::GrottoGrave);
|
||||||
|
|
||||||
//decoupled entrance stuff
|
if (Settings::DecoupleEntrances) {
|
||||||
|
for (Entrance* entrance : entrancePools[EntranceType::GrottoGrave]) {
|
||||||
|
entrancePools[EntranceType::GrottoGraveReverse].push_back(entrance->GetReverse());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//overworld entrances
|
//overworld entrances
|
||||||
if (Settings::ShuffleOverworldEntrances) {
|
if (Settings::ShuffleOverworldEntrances) {
|
||||||
bool excludeOverworldReverse = false; //mix_entrance_pools == all && !decouple_entrances
|
bool excludeOverworldReverse = Settings::MixOverworld && !Settings::DecoupleEntrances;
|
||||||
entrancePools[EntranceType::Overworld] = GetShuffleableEntrances(EntranceType::Overworld, excludeOverworldReverse);
|
entrancePools[EntranceType::Overworld] = GetShuffleableEntrances(EntranceType::Overworld, excludeOverworldReverse);
|
||||||
// if not worlds[0].decouple_entrances:
|
// Only shuffle GV Lower Stream -> Lake Hylia if decoupled entrances are on
|
||||||
// entrance_pools['Overworld'].remove(world.get_entrance('GV Lower Stream -> Lake Hylia'))
|
if (!Settings::DecoupleEntrances) {
|
||||||
if (!excludeOverworldReverse) {
|
FilterAndEraseFromPool(entrancePools[EntranceType::Overworld], [](const Entrance* entrance){return entrance->GetParentRegionKey() == GV_LOWER_STREAM &&
|
||||||
totalRandomizableEntrances -= 26; //Only count each overworld entrance once
|
entrance->GetConnectedRegionKey() == LAKE_HYLIA;});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set shuffled entrances as such
|
||||||
|
SetShuffledEntrances(entrancePools);
|
||||||
|
SetShuffledEntrances(oneWayEntrancePools);
|
||||||
|
|
||||||
|
//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);
|
||||||
|
if (totalMixedPools < 2) {
|
||||||
|
Settings::MixedEntrancePools.SetSelectedIndex(OFF);
|
||||||
|
Settings::MixDungeons.SetSelectedIndex(OFF);
|
||||||
|
Settings::MixOverworld.SetSelectedIndex(OFF);
|
||||||
|
Settings::MixInteriors.SetSelectedIndex(OFF);
|
||||||
|
Settings::MixGrottos.SetSelectedIndex(OFF);
|
||||||
|
}
|
||||||
|
if (Settings::MixedEntrancePools) {
|
||||||
|
std::set<EntranceType> poolsToMix = {};
|
||||||
|
if (Settings::MixDungeons) {
|
||||||
|
poolsToMix.insert(EntranceType::Dungeon);
|
||||||
|
// Insert reverse entrances when decoupled entrances is on
|
||||||
|
if (Settings::DecoupleEntrances) {
|
||||||
|
poolsToMix.insert(EntranceType::DungeonReverse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Settings::MixOverworld) {
|
||||||
|
poolsToMix.insert(EntranceType::Overworld);
|
||||||
|
}
|
||||||
|
if (Settings::MixInteriors) {
|
||||||
|
poolsToMix.insert(EntranceType::Interior);
|
||||||
|
if (Settings::DecoupleEntrances) {
|
||||||
|
poolsToMix.insert(EntranceType::InteriorReverse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Settings::MixGrottos) {
|
||||||
|
poolsToMix.insert(EntranceType::GrottoGrave);
|
||||||
|
if (Settings::DecoupleEntrances) {
|
||||||
|
poolsToMix.insert(EntranceType::GrottoGraveReverse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set shuffled entrances as such
|
|
||||||
for (auto& pool : entrancePools) {
|
for (auto& pool : entrancePools) {
|
||||||
|
|
||||||
|
auto type = pool.first;
|
||||||
|
|
||||||
|
if (poolsToMix.count(type) > 0) {
|
||||||
|
AddElementsToPool(entrancePools[EntranceType::Mixed], pool.second);
|
||||||
|
entrancePools[type].clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build target entrance pools and set the assumption for entrances being reachable
|
||||||
|
EntrancePools oneWayTargetEntrancePools = {};
|
||||||
|
for (auto& pool : oneWayEntrancePools) {
|
||||||
|
|
||||||
|
std::vector<EntranceType> validTargetTypes = {};
|
||||||
|
EntranceType poolType = pool.first;
|
||||||
|
|
||||||
|
if (poolType == EntranceType::OwlDrop) {
|
||||||
|
validTargetTypes = {EntranceType::WarpSong, EntranceType::OwlDrop, EntranceType::Overworld, EntranceType::Extra};
|
||||||
|
oneWayTargetEntrancePools[poolType] = BuildOneWayTargets(validTargetTypes, {std::make_pair(PRELUDE_OF_LIGHT_WARP, TEMPLE_OF_TIME)});
|
||||||
|
// Owl Drops are only accessible as child, so targets should reflect that
|
||||||
|
for (Entrance* target : oneWayTargetEntrancePools[poolType]) {
|
||||||
|
target->SetCondition([]{return Logic::IsChild;});
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (poolType == EntranceType::Spawn) {
|
||||||
|
validTargetTypes = {EntranceType::Spawn, EntranceType::WarpSong, EntranceType::OwlDrop, EntranceType::Overworld, EntranceType::Interior, EntranceType::SpecialInterior, EntranceType::GrottoGrave, EntranceType::Extra};
|
||||||
|
oneWayTargetEntrancePools[poolType] = BuildOneWayTargets(validTargetTypes);
|
||||||
|
|
||||||
|
} else if (poolType == EntranceType::WarpSong) {
|
||||||
|
validTargetTypes = {EntranceType::Spawn, EntranceType::WarpSong, EntranceType::OwlDrop, EntranceType::Overworld, EntranceType::Interior, EntranceType::SpecialInterior, EntranceType::GrottoGrave, EntranceType::Extra};
|
||||||
|
oneWayTargetEntrancePools[poolType] = BuildOneWayTargets(validTargetTypes);
|
||||||
|
}
|
||||||
|
// for target in one_way_target_entrance_pools[pool_type]:
|
||||||
|
// target.add_rule((lambda entrances=entrance_pool: (lambda state, **kwargs: any(entrance.connected_region == None for entrance in entrances)))())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disconnect all one way entrances at this point (they need to be connected during all of the above process)
|
||||||
|
for (auto& pool : oneWayEntrancePools) {
|
||||||
for (Entrance* entrance : pool.second) {
|
for (Entrance* entrance : pool.second) {
|
||||||
entrance->SetAsShuffled();
|
|
||||||
totalRandomizableEntrances++;
|
totalRandomizableEntrances++;
|
||||||
if (entrance->GetReverse() != nullptr) {
|
entrance->Disconnect();
|
||||||
entrance->GetReverse()->SetAsShuffled();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//combine entrance pools if mixing pools
|
// Assume entrance pools for each type
|
||||||
|
EntrancePools targetEntrancePools = {};
|
||||||
//Build target entrance pools and set the assumption for entrances being reachable
|
|
||||||
//one way entrance stuff
|
|
||||||
|
|
||||||
//assume entrance pools for each type
|
|
||||||
std::map<EntranceType, std::vector<Entrance*>> targetEntrancePools = {};
|
|
||||||
for (auto& pool : entrancePools) {
|
for (auto& pool : entrancePools) {
|
||||||
targetEntrancePools[pool.first] = AssumeEntrancePool(pool.second);
|
targetEntrancePools[pool.first] = AssumeEntrancePool(pool.second);
|
||||||
}
|
}
|
||||||
@ -819,9 +1122,56 @@ int ShuffleAllEntrances() {
|
|||||||
//remove replaced entrances so we don't place two in one target
|
//remove replaced entrances so we don't place two in one target
|
||||||
//remvoe priority targets if any placed entrances point at their regions
|
//remvoe priority targets if any placed entrances point at their regions
|
||||||
|
|
||||||
//place priority entrances
|
// Place priority entrances
|
||||||
|
ShuffleOneWayPriorityEntrances(oneWayPriorities, oneWayEntrancePools, oneWayTargetEntrancePools);
|
||||||
|
if (entranceShuffleFailure) {
|
||||||
|
return ENTRANCE_SHUFFLE_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
//delete all targets that we just placed from one way target pools so multiple one way entrances don't use the same target
|
// Delete all targets that we just placed from one way target pools so
|
||||||
|
// multiple one way entrances don't use the same target
|
||||||
|
std::vector<Entrance*> replacedEntrances = {};
|
||||||
|
for (auto& pool : oneWayEntrancePools) {
|
||||||
|
for (Entrance* entrance : pool.second) {
|
||||||
|
if (entrance->GetReplacement() != nullptr) {
|
||||||
|
replacedEntrances.push_back(entrance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& pool : oneWayTargetEntrancePools) {
|
||||||
|
for (Entrance* remainingTarget : pool.second) {
|
||||||
|
auto replacement = remainingTarget->GetReplacement();
|
||||||
|
if (ElementInContainer(replacement, replacedEntrances)) {
|
||||||
|
DeleteTargetEntrance(remainingTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shuffle all one way entrances among pools to shuffle
|
||||||
|
for (auto& pool : oneWayEntrancePools) {
|
||||||
|
ShuffleEntrancePool(pool.second, oneWayTargetEntrancePools[pool.first], 5);
|
||||||
|
if (entranceShuffleFailure) {
|
||||||
|
return ENTRANCE_SHUFFLE_FAILURE;
|
||||||
|
}
|
||||||
|
// Delete all targets that we just placed from other one way target pools so
|
||||||
|
// multiple one way entrances don't use the same target
|
||||||
|
replacedEntrances = FilterFromPool(pool.second, [](Entrance* entrance){
|
||||||
|
return entrance->GetReplacement() != nullptr;
|
||||||
|
});
|
||||||
|
for (auto& targetPool : oneWayTargetEntrancePools) {
|
||||||
|
for (Entrance* remainingTarget : targetPool.second) {
|
||||||
|
auto replacement = remainingTarget->GetReplacement();
|
||||||
|
if (ElementInContainer(replacement, replacedEntrances)) {
|
||||||
|
DeleteTargetEntrance(remainingTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Delete all unused extra targets after placing a one way pool, since the
|
||||||
|
// unused targets won't ever be replaced
|
||||||
|
for (Entrance* unusedTarget : oneWayTargetEntrancePools[pool.first]) {
|
||||||
|
DeleteTargetEntrance(unusedTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//shuffle all entrances among pools to shuffle
|
//shuffle all entrances among pools to shuffle
|
||||||
for (auto& pool : entrancePools) {
|
for (auto& pool : entrancePools) {
|
||||||
@ -834,7 +1184,7 @@ int ShuffleAllEntrances() {
|
|||||||
return ENTRANCE_SHUFFLE_SUCCESS;
|
return ENTRANCE_SHUFFLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create the set of entrances that will be overridden
|
// Save the set of shuffled entrances that will be sent to the patch
|
||||||
void CreateEntranceOverrides() {
|
void CreateEntranceOverrides() {
|
||||||
entranceOverrides.clear();
|
entranceOverrides.clear();
|
||||||
if (noRandomEntrances) {
|
if (noRandomEntrances) {
|
||||||
@ -854,10 +1204,18 @@ void CreateEntranceOverrides() {
|
|||||||
SPDLOG_DEBUG(message);
|
SPDLOG_DEBUG(message);
|
||||||
|
|
||||||
int16_t originalIndex = entrance->GetIndex();
|
int16_t originalIndex = entrance->GetIndex();
|
||||||
int16_t destinationIndex = entrance->GetReverse()->GetIndex();
|
|
||||||
int16_t originalBlueWarp = entrance->GetBlueWarp();
|
int16_t originalBlueWarp = entrance->GetBlueWarp();
|
||||||
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
||||||
int16_t replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
|
||||||
|
int16_t destinationIndex = -1;
|
||||||
|
int16_t replacementDestinationIndex = -1;
|
||||||
|
|
||||||
|
// Only set destination indices for two way entrances and when decouple entrances
|
||||||
|
// is off
|
||||||
|
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||||
|
replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
||||||
|
destinationIndex = entrance->GetReverse()->GetIndex();
|
||||||
|
}
|
||||||
|
|
||||||
entranceOverrides.push_back({
|
entranceOverrides.push_back({
|
||||||
.index = originalIndex,
|
.index = originalIndex,
|
||||||
|
@ -21,11 +21,15 @@ enum class EntranceType {
|
|||||||
WarpSong,
|
WarpSong,
|
||||||
Dungeon,
|
Dungeon,
|
||||||
GanonDungeon,
|
GanonDungeon,
|
||||||
|
DungeonReverse,
|
||||||
Interior,
|
Interior,
|
||||||
|
InteriorReverse,
|
||||||
SpecialInterior,
|
SpecialInterior,
|
||||||
GrottoGrave,
|
GrottoGrave,
|
||||||
|
GrottoGraveReverse,
|
||||||
Overworld,
|
Overworld,
|
||||||
Extra,
|
Extra,
|
||||||
|
Mixed,
|
||||||
All,
|
All,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -40,6 +44,11 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resets the glitchless condition for the entrance
|
||||||
|
void SetCondition(ConditionFn newCondition) {
|
||||||
|
conditions_met[0] = newCondition;
|
||||||
|
}
|
||||||
|
|
||||||
bool GetConditionsMet() const {
|
bool GetConditionsMet() const {
|
||||||
if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
|
if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -296,7 +296,7 @@ std::vector<uint32_t> GetAccessibleLocations(const std::vector<uint32_t>& allowe
|
|||||||
entranceSphere.push_back(&exit);
|
entranceSphere.push_back(&exit);
|
||||||
exit.AddToPool();
|
exit.AddToPool();
|
||||||
// Don't list a coupled entrance from both directions
|
// Don't list a coupled entrance from both directions
|
||||||
if (exit.GetReplacement()->GetReverse() != nullptr /*&& !DecoupleEntrances*/) {
|
if (exit.GetReplacement()->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||||
exit.GetReplacement()->GetReverse()->AddToPool();
|
exit.GetReplacement()->GetReverse()->AddToPool();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,12 @@ Text childAltarText;
|
|||||||
Text adultAltarText;
|
Text adultAltarText;
|
||||||
Text ganonText;
|
Text ganonText;
|
||||||
Text ganonHintText;
|
Text ganonHintText;
|
||||||
|
Text warpMinuetText;
|
||||||
|
Text warpBoleroText;
|
||||||
|
Text warpSerenadeText;
|
||||||
|
Text warpRequiemText;
|
||||||
|
Text warpNocturneText;
|
||||||
|
Text warpPreludeText;
|
||||||
|
|
||||||
Text& GetChildAltarText() {
|
Text& GetChildAltarText() {
|
||||||
return childAltarText;
|
return childAltarText;
|
||||||
@ -133,6 +139,30 @@ Text& GetGanonHintText() {
|
|||||||
return ganonHintText;
|
return ganonHintText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Text& GetWarpMinuetText() {
|
||||||
|
return warpMinuetText;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text& GetWarpBoleroText() {
|
||||||
|
return warpBoleroText;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text& GetWarpSerenadeText() {
|
||||||
|
return warpSerenadeText;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text& GetWarpRequiemText() {
|
||||||
|
return warpRequiemText;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text& GetWarpNocturneText() {
|
||||||
|
return warpNocturneText;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text& GetWarpPreludeText() {
|
||||||
|
return warpPreludeText;
|
||||||
|
}
|
||||||
|
|
||||||
static Area* GetHintRegion(const uint32_t area) {
|
static Area* GetHintRegion(const uint32_t area) {
|
||||||
|
|
||||||
std::vector<uint32_t> alreadyChecked = {};
|
std::vector<uint32_t> alreadyChecked = {};
|
||||||
@ -707,10 +737,49 @@ void CreateMerchantsHints() {
|
|||||||
CreateMessageFromTextObject(0x6078, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextTwo, {QM_RED, QM_YELLOW, QM_RED}));
|
CreateMessageFromTextObject(0x6078, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextTwo, {QM_RED, QM_YELLOW, QM_RED}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CreateWarpSongTexts() {
|
||||||
|
auto warpSongEntrances = GetShuffleableEntrances(EntranceType::WarpSong, false);
|
||||||
|
|
||||||
|
for (auto entrance : warpSongEntrances) {
|
||||||
|
Text resolvedHint;
|
||||||
|
// Start with entrance location text
|
||||||
|
auto region = entrance->GetConnectedRegion()->regionName;
|
||||||
|
resolvedHint = Text{"","",""} + region;
|
||||||
|
|
||||||
|
auto destination = entrance->GetConnectedRegion()->GetHint().GetText();
|
||||||
|
// Prefer hint location when available
|
||||||
|
if (destination.GetEnglish() != "No Hint") {
|
||||||
|
resolvedHint = destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (entrance->GetIndex()) {
|
||||||
|
case 0x0600: // minuet
|
||||||
|
warpMinuetText = resolvedHint;
|
||||||
|
break;
|
||||||
|
case 0x04F6: // bolero
|
||||||
|
warpBoleroText = resolvedHint;
|
||||||
|
break;
|
||||||
|
case 0x0604: // serenade
|
||||||
|
warpSerenadeText = resolvedHint;
|
||||||
|
break;
|
||||||
|
case 0x01F1: // requiem
|
||||||
|
warpRequiemText = resolvedHint;
|
||||||
|
break;
|
||||||
|
case 0x0568: // nocturne
|
||||||
|
warpNocturneText = resolvedHint;
|
||||||
|
break;
|
||||||
|
case 0x05F4: // prelude
|
||||||
|
warpPreludeText = resolvedHint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CreateAllHints() {
|
void CreateAllHints() {
|
||||||
|
|
||||||
CreateGanonText();
|
CreateGanonText();
|
||||||
CreateAltarText();
|
CreateAltarText();
|
||||||
|
CreateWarpSongTexts();
|
||||||
|
|
||||||
SPDLOG_DEBUG("\nNOW CREATING HINTS\n");
|
SPDLOG_DEBUG("\nNOW CREATING HINTS\n");
|
||||||
const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value<uint8_t>()];
|
const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value<uint8_t>()];
|
||||||
|
@ -225,3 +225,10 @@ Text& GetChildAltarText();
|
|||||||
Text& GetAdultAltarText();
|
Text& GetAdultAltarText();
|
||||||
Text& GetGanonText();
|
Text& GetGanonText();
|
||||||
Text& GetGanonHintText();
|
Text& GetGanonHintText();
|
||||||
|
|
||||||
|
Text& GetWarpMinuetText();
|
||||||
|
Text& GetWarpBoleroText();
|
||||||
|
Text& GetWarpSerenadeText();
|
||||||
|
Text& GetWarpRequiemText();
|
||||||
|
Text& GetWarpNocturneText();
|
||||||
|
Text& GetWarpPreludeText();
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
using HintKey = uint32_t;
|
||||||
|
using ItemKey = uint32_t;
|
||||||
|
using LocationKey = uint32_t;
|
||||||
using AreaKey = uint32_t;
|
using AreaKey = uint32_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -1082,6 +1085,14 @@ typedef enum {
|
|||||||
//AREAS
|
//AREAS
|
||||||
ROOT,
|
ROOT,
|
||||||
ROOT_EXITS,
|
ROOT_EXITS,
|
||||||
|
CHILD_SPAWN,
|
||||||
|
ADULT_SPAWN,
|
||||||
|
MINUET_OF_FOREST_WARP,
|
||||||
|
BOLERO_OF_FIRE_WARP,
|
||||||
|
SERENADE_OF_WATER_WARP,
|
||||||
|
REQUIEM_OF_SPIRIT_WARP,
|
||||||
|
NOCTURNE_OF_SHADOW_WARP,
|
||||||
|
PRELUDE_OF_LIGHT_WARP,
|
||||||
KOKIRI_FOREST,
|
KOKIRI_FOREST,
|
||||||
KF_LINKS_HOUSE,
|
KF_LINKS_HOUSE,
|
||||||
KF_MIDOS_HOUSE,
|
KF_MIDOS_HOUSE,
|
||||||
@ -1135,6 +1146,7 @@ typedef enum {
|
|||||||
HAUNTED_WASTELAND,
|
HAUNTED_WASTELAND,
|
||||||
WASTELAND_NEAR_COLOSSUS,
|
WASTELAND_NEAR_COLOSSUS,
|
||||||
DESERT_COLOSSUS,
|
DESERT_COLOSSUS,
|
||||||
|
DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY,
|
||||||
COLOSSUS_GREAT_FAIRY_FOUNTAIN,
|
COLOSSUS_GREAT_FAIRY_FOUNTAIN,
|
||||||
COLOSSUS_GROTTO,
|
COLOSSUS_GROTTO,
|
||||||
MARKET_ENTRANCE,
|
MARKET_ENTRANCE,
|
||||||
@ -1173,6 +1185,7 @@ typedef enum {
|
|||||||
KAK_POTION_SHOP_FRONT,
|
KAK_POTION_SHOP_FRONT,
|
||||||
KAK_POTION_SHOP_BACK,
|
KAK_POTION_SHOP_BACK,
|
||||||
KAK_ROOFTOP,
|
KAK_ROOFTOP,
|
||||||
|
KAK_IMPAS_ROOFTOP,
|
||||||
KAK_BEHIND_GATE,
|
KAK_BEHIND_GATE,
|
||||||
KAK_BACKYARD,
|
KAK_BACKYARD,
|
||||||
KAK_ODD_POTION_BUILDING,
|
KAK_ODD_POTION_BUILDING,
|
||||||
|
@ -264,25 +264,66 @@ void AreaTable_Init() {
|
|||||||
|
|
||||||
areaTable[ROOT_EXITS] = Area("Root Exits", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[ROOT_EXITS] = Area("Root Exits", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(KF_LINKS_HOUSE, {[]{return IsChild;}}),
|
Entrance(CHILD_SPAWN, {[]{return IsChild;}}),
|
||||||
Entrance(TEMPLE_OF_TIME, {[]{return (CanPlay(PreludeOfLight) && CanLeaveForest) || IsAdult;},
|
Entrance(ADULT_SPAWN, {[]{return IsAdult;}}),
|
||||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
Entrance(MINUET_OF_FOREST_WARP, {[]{return CanPlay(MinuetOfForest);},
|
||||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && PreludeOfLight && CanLeaveForest;}}),
|
|
||||||
Entrance(SACRED_FOREST_MEADOW, {[]{return CanPlay(MinuetOfForest);},
|
|
||||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && MinuetOfForest;}}),
|
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && MinuetOfForest;}}),
|
||||||
Entrance(DMC_CENTRAL_LOCAL, {[]{return CanPlay(BoleroOfFire) && CanLeaveForest;},
|
Entrance(BOLERO_OF_FIRE_WARP, {[]{return CanPlay(BoleroOfFire) && CanLeaveForest;},
|
||||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && BoleroOfFire && CanLeaveForest;}}),
|
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && BoleroOfFire && CanLeaveForest;}}),
|
||||||
Entrance(LAKE_HYLIA, {[]{return CanPlay(SerenadeOfWater) && CanLeaveForest;},
|
Entrance(SERENADE_OF_WATER_WARP, {[]{return CanPlay(SerenadeOfWater) && CanLeaveForest;},
|
||||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && SerenadeOfWater && CanLeaveForest;}}),
|
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && SerenadeOfWater && CanLeaveForest;}}),
|
||||||
Entrance(GRAVEYARD_WARP_PAD_REGION, {[]{return CanPlay(NocturneOfShadow) && CanLeaveForest;},
|
Entrance(NOCTURNE_OF_SHADOW_WARP, {[]{return CanPlay(NocturneOfShadow) && CanLeaveForest;},
|
||||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && NocturneOfShadow && CanLeaveForest;}}),
|
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && NocturneOfShadow && CanLeaveForest;}}),
|
||||||
Entrance(DESERT_COLOSSUS, {[]{return CanPlay(RequiemOfSpirit) && CanLeaveForest;},
|
Entrance(REQUIEM_OF_SPIRIT_WARP, {[]{return CanPlay(RequiemOfSpirit) && CanLeaveForest;},
|
||||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && RequiemOfSpirit && CanLeaveForest;}}),
|
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && RequiemOfSpirit && CanLeaveForest;}}),
|
||||||
|
Entrance(PRELUDE_OF_LIGHT_WARP, {[]{return CanPlay(PreludeOfLight) && CanLeaveForest;},
|
||||||
|
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||||
|
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && PreludeOfLight && CanLeaveForest;}}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[CHILD_SPAWN] = Area("Child Spawn", "", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
//Exits
|
||||||
|
Entrance(KF_LINKS_HOUSE, {[]{return true;}}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[ADULT_SPAWN] = Area("Adult Spawn", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
//Exits
|
||||||
|
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[MINUET_OF_FOREST_WARP] = Area("Minuet of Forest Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
//Exits
|
||||||
|
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[BOLERO_OF_FIRE_WARP] = Area("Bolero of Fire Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
//Exits
|
||||||
|
Entrance(DMC_CENTRAL_LOCAL, {[]{return true;}}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[SERENADE_OF_WATER_WARP] = Area("Serenade of Water Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
//Exits
|
||||||
|
Entrance(LAKE_HYLIA, {[]{return true;}}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[REQUIEM_OF_SPIRIT_WARP] = Area("Requiem of Spirit Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
//Exits
|
||||||
|
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[NOCTURNE_OF_SHADOW_WARP] = Area("Nocturne of Shadow Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
//Exits
|
||||||
|
Entrance(GRAVEYARD_WARP_PAD_REGION, {[]{return true;}}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[PRELUDE_OF_LIGHT_WARP] = Area("Prelude of Light Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
//Exits
|
||||||
|
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Overworld
|
// Overworld
|
||||||
@ -330,10 +371,19 @@ void AreaTable_Init() {
|
|||||||
|
|
||||||
namespace Areas {
|
namespace Areas {
|
||||||
|
|
||||||
static std::array<const uint32_t, 414> allAreas = {
|
static std::array<const uint32_t, 424> allAreas = {
|
||||||
ROOT,
|
ROOT,
|
||||||
ROOT_EXITS,
|
ROOT_EXITS,
|
||||||
|
|
||||||
|
CHILD_SPAWN,
|
||||||
|
ADULT_SPAWN,
|
||||||
|
MINUET_OF_FOREST_WARP,
|
||||||
|
BOLERO_OF_FIRE_WARP,
|
||||||
|
SERENADE_OF_WATER_WARP,
|
||||||
|
REQUIEM_OF_SPIRIT_WARP,
|
||||||
|
NOCTURNE_OF_SHADOW_WARP,
|
||||||
|
PRELUDE_OF_LIGHT_WARP,
|
||||||
|
|
||||||
KOKIRI_FOREST,
|
KOKIRI_FOREST,
|
||||||
KF_LINKS_HOUSE,
|
KF_LINKS_HOUSE,
|
||||||
KF_MIDOS_HOUSE,
|
KF_MIDOS_HOUSE,
|
||||||
@ -373,6 +423,7 @@ namespace Areas {
|
|||||||
KAK_POTION_SHOP_FRONT,
|
KAK_POTION_SHOP_FRONT,
|
||||||
KAK_POTION_SHOP_BACK,
|
KAK_POTION_SHOP_BACK,
|
||||||
KAK_ROOFTOP,
|
KAK_ROOFTOP,
|
||||||
|
KAK_IMPAS_ROOFTOP,
|
||||||
KAK_BEHIND_GATE,
|
KAK_BEHIND_GATE,
|
||||||
KAK_BACKYARD,
|
KAK_BACKYARD,
|
||||||
KAK_ODD_POTION_BUILDING,
|
KAK_ODD_POTION_BUILDING,
|
||||||
@ -473,6 +524,7 @@ namespace Areas {
|
|||||||
HAUNTED_WASTELAND,
|
HAUNTED_WASTELAND,
|
||||||
WASTELAND_NEAR_COLOSSUS,
|
WASTELAND_NEAR_COLOSSUS,
|
||||||
DESERT_COLOSSUS,
|
DESERT_COLOSSUS,
|
||||||
|
DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY,
|
||||||
COLOSSUS_GREAT_FAIRY_FOUNTAIN,
|
COLOSSUS_GREAT_FAIRY_FOUNTAIN,
|
||||||
COLOSSUS_GROTTO,
|
COLOSSUS_GROTTO,
|
||||||
SPIRIT_TEMPLE_ENTRYWAY,
|
SPIRIT_TEMPLE_ENTRYWAY,
|
||||||
|
@ -50,7 +50,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
|
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[TEMPLE_OF_TIME] = Area("Temple of Time", "", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[TEMPLE_OF_TIME] = Area("Temple of Time", "Temple of Time", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(TOT_LIGHT_ARROWS_CUTSCENE, {[]{return IsAdult && CanTriggerLACS;}}),
|
LocationAccess(TOT_LIGHT_ARROWS_CUTSCENE, {[]{return IsAdult && CanTriggerLACS;}}),
|
||||||
}, {
|
}, {
|
||||||
@ -61,7 +61,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
((Bugs || Fish) && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE)));}}),
|
((Bugs || Fish) && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE)));}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[TOT_BEYOND_DOOR_OF_TIME] = Area("Beyond Door of Time", "", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {
|
areaTable[TOT_BEYOND_DOOR_OF_TIME] = Area("Beyond Door of Time", "Beyond Door of Time", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
//EventAccess(&TimeTravel, {[]{return true;}}),
|
//EventAccess(&TimeTravel, {[]{return true;}}),
|
||||||
}, {
|
}, {
|
||||||
@ -111,7 +111,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(HYRULE_CASTLE_GROUNDS, {[]{return true;}}),
|
Entrance(HYRULE_CASTLE_GROUNDS, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[HC_GREAT_FAIRY_FOUNTAIN] = Area("HC Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[HC_GREAT_FAIRY_FOUNTAIN] = Area("HC Great Fairy Fountain", "HC Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(HC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
LocationAccess(HC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
||||||
@ -120,7 +120,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
|
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[HC_STORMS_GROTTO] = Area("HC Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[HC_STORMS_GROTTO] = Area("HC Storms Grotto", "HC Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&NutPot, {[]{return NutPot || CanBlastOrSmash;}}),
|
EventAccess(&NutPot, {[]{return NutPot || CanBlastOrSmash;}}),
|
||||||
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || (CanBlastOrSmash && CanSummonGossipFairy);}}),
|
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || (CanBlastOrSmash && CanSummonGossipFairy);}}),
|
||||||
@ -146,7 +146,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
/*Glitched*/[]{return (HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::ADVANCED) || (HoverBoots && CanShield && Bombs && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::EXPERT)) || (HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::ADVANCED));}}),
|
/*Glitched*/[]{return (HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::ADVANCED) || (HoverBoots && CanShield && Bombs && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::EXPERT)) || (HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::ADVANCED));}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[OGC_GREAT_FAIRY_FOUNTAIN] = Area("OGC Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[OGC_GREAT_FAIRY_FOUNTAIN] = Area("OGC Great Fairy Fountain", "OGC Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(OGC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
LocationAccess(OGC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
||||||
@ -155,7 +155,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
|
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[MARKET_GUARD_HOUSE] = Area("Market Guard House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[MARKET_GUARD_HOUSE] = Area("Market Guard House", "Market Guard House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(MARKET_10_BIG_POES, {[]{return IsAdult && BigPoeKill;}}),
|
LocationAccess(MARKET_10_BIG_POES, {[]{return IsAdult && BigPoeKill;}}),
|
||||||
LocationAccess(MARKET_GS_GUARD_HOUSE, {[]{return IsChild;}}),
|
LocationAccess(MARKET_GS_GUARD_HOUSE, {[]{return IsChild;}}),
|
||||||
@ -164,7 +164,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(MARKET_ENTRANCE, {[]{return true;}}),
|
Entrance(MARKET_ENTRANCE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[MARKET_BAZAAR] = Area("Market Bazaar", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[MARKET_BAZAAR] = Area("Market Bazaar", "Market Bazaar", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(MARKET_BAZAAR_ITEM_1, {[]{return true;}}),
|
LocationAccess(MARKET_BAZAAR_ITEM_1, {[]{return true;}}),
|
||||||
LocationAccess(MARKET_BAZAAR_ITEM_2, {[]{return true;}}),
|
LocationAccess(MARKET_BAZAAR_ITEM_2, {[]{return true;}}),
|
||||||
@ -179,7 +179,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(THE_MARKET, {[]{return true;}}),
|
Entrance(THE_MARKET, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[MARKET_MASK_SHOP] = Area("Market Mask Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[MARKET_MASK_SHOP] = Area("Market Mask Shop", "Market Mask Shop", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&SkullMask, {[]{return SkullMask || (ZeldasLetter && (CompleteMaskQuest || ChildCanAccess(KAKARIKO_VILLAGE)));}}),
|
EventAccess(&SkullMask, {[]{return SkullMask || (ZeldasLetter && (CompleteMaskQuest || ChildCanAccess(KAKARIKO_VILLAGE)));}}),
|
||||||
EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (CompleteMaskQuest || (ChildCanAccess(THE_LOST_WOODS) && CanPlay(SariasSong) && AreaTable(THE_GRAVEYARD)->childDay && ChildCanAccess(HYRULE_FIELD) && HasAllStones)));}}),
|
EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (CompleteMaskQuest || (ChildCanAccess(THE_LOST_WOODS) && CanPlay(SariasSong) && AreaTable(THE_GRAVEYARD)->childDay && ChildCanAccess(HYRULE_FIELD) && HasAllStones)));}}),
|
||||||
@ -188,7 +188,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(THE_MARKET, {[]{return true;}}),
|
Entrance(THE_MARKET, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[MARKET_SHOOTING_GALLERY] = Area("Market Shooting Gallery", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[MARKET_SHOOTING_GALLERY] = Area("Market Shooting Gallery", "Market Shooting Gallery", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(MARKET_SHOOTING_GALLERY_REWARD, {[]{return IsChild;}}),
|
LocationAccess(MARKET_SHOOTING_GALLERY_REWARD, {[]{return IsChild;}}),
|
||||||
}, {
|
}, {
|
||||||
@ -196,7 +196,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(THE_MARKET, {[]{return true;}}),
|
Entrance(THE_MARKET, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[MARKET_BOMBCHU_BOWLING] = Area("Market Bombchu Bowling", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[MARKET_BOMBCHU_BOWLING] = Area("Market Bombchu Bowling", "Market Bombchu Bowling", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, {[]{return CanPlayBowling;}}),
|
LocationAccess(MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, {[]{return CanPlayBowling;}}),
|
||||||
LocationAccess(MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, {[]{return CanPlayBowling;}}),
|
LocationAccess(MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, {[]{return CanPlayBowling;}}),
|
||||||
@ -206,7 +206,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(THE_MARKET, {[]{return true;}}),
|
Entrance(THE_MARKET, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[MARKET_POTION_SHOP] = Area("Market Potion Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[MARKET_POTION_SHOP] = Area("Market Potion Shop", "Market Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(MARKET_POTION_SHOP_ITEM_1, {[]{return true;}}),
|
LocationAccess(MARKET_POTION_SHOP_ITEM_1, {[]{return true;}}),
|
||||||
LocationAccess(MARKET_POTION_SHOP_ITEM_2, {[]{return true;}}),
|
LocationAccess(MARKET_POTION_SHOP_ITEM_2, {[]{return true;}}),
|
||||||
@ -221,7 +221,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(THE_MARKET, {[]{return true;}}),
|
Entrance(THE_MARKET, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "Market Treasure Chest Game", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(LENS_OF_TRUTH) && !ShuffleChestMinigame) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 6)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 1));},
|
LocationAccess(MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(LENS_OF_TRUTH) && !ShuffleChestMinigame) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 6)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 1));},
|
||||||
/*Glitched*/[]{return !ShuffleChestMinigame && (CanUse(FARORES_WIND) && (HasBottle || WeirdEgg) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE));}}),
|
/*Glitched*/[]{return !ShuffleChestMinigame && (CanUse(FARORES_WIND) && (HasBottle || WeirdEgg) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE));}}),
|
||||||
@ -235,7 +235,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(THE_MARKET, {[]{return true;}}),
|
Entrance(THE_MARKET, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[MARKET_BOMBCHU_SHOP] = Area("Market Bombchu Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[MARKET_BOMBCHU_SHOP] = Area("Market Bombchu Shop", "Market Bombchu Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_1, {[]{return true;}}),
|
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_1, {[]{return true;}}),
|
||||||
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_2, {[]{return true;}}),
|
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_2, {[]{return true;}}),
|
||||||
@ -250,7 +250,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
|
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[MARKET_DOG_LADY_HOUSE] = Area("Market Dog Lady House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[MARKET_DOG_LADY_HOUSE] = Area("Market Dog Lady House", "Market Dog Lady House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(MARKET_LOST_DOG, {[]{return IsChild && AtNight;}}),
|
LocationAccess(MARKET_LOST_DOG, {[]{return IsChild && AtNight;}}),
|
||||||
}, {
|
}, {
|
||||||
@ -258,7 +258,7 @@ void AreaTable_Init_CastleTown() {
|
|||||||
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
|
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[MARKET_MAN_IN_GREEN_HOUSE] = Area("Market Man in Green House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[MARKET_MAN_IN_GREEN_HOUSE] = Area("Market Man in Green House", "Market Man in Green House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
|
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
@ -55,10 +55,10 @@ void AreaTable_Init_DeathMountain() {
|
|||||||
|
|
||||||
areaTable[DMT_OWL_FLIGHT] = Area("DMT Owl Flight", "Death Mountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[DMT_OWL_FLIGHT] = Area("DMT Owl Flight", "Death Mountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(KAK_IMPAS_LEDGE, {[]{return true;}}),
|
Entrance(KAK_IMPAS_ROOFTOP, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[DMT_COW_GROTTO] = Area("DMT Cow Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[DMT_COW_GROTTO] = Area("DMT Cow Grotto", "DMT Cow Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(DMT_COW_GROTTO_COW, {[]{return CanPlay(EponasSong);},
|
LocationAccess(DMT_COW_GROTTO_COW, {[]{return CanPlay(EponasSong);},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||||
@ -69,7 +69,7 @@ void AreaTable_Init_DeathMountain() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[DMT_STORMS_GROTTO] = Area("DMT Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
areaTable[DMT_STORMS_GROTTO] = Area("DMT Storms Grotto", "DMT Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(DMT_STORMS_GROTTO_CHEST, {[]{return true;}}),
|
LocationAccess(DMT_STORMS_GROTTO_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(DMT_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
LocationAccess(DMT_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||||
@ -78,7 +78,7 @@ void AreaTable_Init_DeathMountain() {
|
|||||||
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
|
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[DMT_GREAT_FAIRY_FOUNTAIN] = Area("DMT Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[DMT_GREAT_FAIRY_FOUNTAIN] = Area("DMT Great Fairy Fountain", "DMT Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(DMT_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
LocationAccess(DMT_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||||
@ -156,7 +156,7 @@ void AreaTable_Init_DeathMountain() {
|
|||||||
Entrance(GORON_CITY, {[]{return EffectiveHealth > 2 || CanUse(GORON_TUNIC) || CanUse(NAYRUS_LOVE) || ((IsChild || CanPlay(SongOfTime)) && CanUse(LONGSHOT));}}),
|
Entrance(GORON_CITY, {[]{return EffectiveHealth > 2 || CanUse(GORON_TUNIC) || CanUse(NAYRUS_LOVE) || ((IsChild || CanPlay(SongOfTime)) && CanUse(LONGSHOT));}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GC_SHOP] = Area("GC Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[GC_SHOP] = Area("GC Shop", "GC Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(GC_SHOP_ITEM_1, {[]{return true;}}),
|
LocationAccess(GC_SHOP_ITEM_1, {[]{return true;}}),
|
||||||
LocationAccess(GC_SHOP_ITEM_2, {[]{return true;}}),
|
LocationAccess(GC_SHOP_ITEM_2, {[]{return true;}}),
|
||||||
@ -171,7 +171,7 @@ void AreaTable_Init_DeathMountain() {
|
|||||||
Entrance(GORON_CITY, {[]{return true;}}),
|
Entrance(GORON_CITY, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GC_GROTTO] = Area("GC Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[GC_GROTTO] = Area("GC Grotto", "GC Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(GC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
|
LocationAccess(GC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
|
||||||
LocationAccess(GC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
|
LocationAccess(GC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
|
||||||
@ -262,7 +262,7 @@ void AreaTable_Init_DeathMountain() {
|
|||||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) && FireTimer >= 48;}}),
|
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) && FireTimer >= 48;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "DMC Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(DMC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
LocationAccess(DMC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanTakeDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanTakeDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||||
@ -272,7 +272,7 @@ void AreaTable_Init_DeathMountain() {
|
|||||||
Entrance(DMC_LOWER_LOCAL, {[]{return true;}}),
|
Entrance(DMC_LOWER_LOCAL, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[DMC_UPPER_GROTTO] = Area("DMC Upper Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
areaTable[DMC_UPPER_GROTTO] = Area("DMC Upper Grotto", "DMC Upper Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(DMC_UPPER_GROTTO_CHEST, {[]{return true;}}),
|
LocationAccess(DMC_UPPER_GROTTO_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(DMC_UPPER_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
LocationAccess(DMC_UPPER_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||||
@ -281,7 +281,7 @@ void AreaTable_Init_DeathMountain() {
|
|||||||
Entrance(DMC_UPPER_LOCAL, {[]{return true;}}),
|
Entrance(DMC_UPPER_LOCAL, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[DMC_HAMMER_GROTTO] = Area("DMC Hammer Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[DMC_HAMMER_GROTTO] = Area("DMC Hammer Grotto", "DMC Hammer Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(DMC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
|
LocationAccess(DMC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
|
||||||
LocationAccess(DMC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
|
LocationAccess(DMC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
|
||||||
|
@ -84,17 +84,17 @@ void AreaTable_Init_GerudoValley() {
|
|||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsAdult && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsAdult && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GV_CARPENTER_TENT] = Area("GV Carpenter Tent", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[GV_CARPENTER_TENT] = Area("GV Carpenter Tent", "GV Carpenter Tent", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(GV_FORTRESS_SIDE, {[]{return true;}}),
|
Entrance(GV_FORTRESS_SIDE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GV_OCTOROK_GROTTO] = Area("GV Octorok Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[GV_OCTOROK_GROTTO] = Area("GV Octorok Grotto", "GV Octorok Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(GV_GROTTO_LEDGE, {[]{return true;}}),
|
Entrance(GV_GROTTO_LEDGE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GV_STORMS_GROTTO] = Area("GV Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[GV_STORMS_GROTTO] = Area("GV Storms Grotto", "GV Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(GV_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
LocationAccess(GV_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||||
LocationAccess(GV_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
LocationAccess(GV_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||||
@ -148,7 +148,7 @@ void AreaTable_Init_GerudoValley() {
|
|||||||
Entrance(WASTELAND_NEAR_FORTRESS, {[]{return true;}}),
|
Entrance(WASTELAND_NEAR_FORTRESS, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GF_STORMS_GROTTO] = Area("GF Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[GF_STORMS_GROTTO] = Area("GF Storms Grotto", "GF Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||||
}, {}, {
|
}, {}, {
|
||||||
@ -200,7 +200,6 @@ void AreaTable_Init_GerudoValley() {
|
|||||||
LocationAccess(COLOSSUS_FREESTANDING_POH, {[]{return IsAdult && CanPlantBean(DESERT_COLOSSUS);},
|
LocationAccess(COLOSSUS_FREESTANDING_POH, {[]{return IsAdult && CanPlantBean(DESERT_COLOSSUS);},
|
||||||
/*Glitched*/[]{return (HoverBoots && CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED)) || (((IsChild && (ChildCanAccess(SPIRIT_TEMPLE_OUTDOOR_HANDS) || ChildCanAccess(SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND) || ChildCanAccess(SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND))) ||
|
/*Glitched*/[]{return (HoverBoots && CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED)) || (((IsChild && (ChildCanAccess(SPIRIT_TEMPLE_OUTDOOR_HANDS) || ChildCanAccess(SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND) || ChildCanAccess(SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND))) ||
|
||||||
(IsAdult && (AdultCanAccess(SPIRIT_TEMPLE_OUTDOOR_HANDS) || AdultCanAccess(SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND) || AdultCanAccess(SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND)))) && (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::ADVANCED) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE)));}}),
|
(IsAdult && (AdultCanAccess(SPIRIT_TEMPLE_OUTDOOR_HANDS) || AdultCanAccess(SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND) || AdultCanAccess(SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND)))) && (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::ADVANCED) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE)));}}),
|
||||||
LocationAccess(SHEIK_AT_COLOSSUS, {[]{return true;}}),
|
|
||||||
LocationAccess(COLOSSUS_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
|
LocationAccess(COLOSSUS_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
|
||||||
LocationAccess(COLOSSUS_GS_TREE, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
|
LocationAccess(COLOSSUS_GS_TREE, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
|
||||||
LocationAccess(COLOSSUS_GS_HILL, {[]{return IsAdult && AtNight && (CanPlantBean(DESERT_COLOSSUS) || CanUse(LONGSHOT) || (LogicColossusGS && CanUse(HOOKSHOT))) && CanGetNightTimeGS;},
|
LocationAccess(COLOSSUS_GS_HILL, {[]{return IsAdult && AtNight && (CanPlantBean(DESERT_COLOSSUS) || CanUse(LONGSHOT) || (LogicColossusGS && CanUse(HOOKSHOT))) && CanGetNightTimeGS;},
|
||||||
@ -214,7 +213,15 @@ void AreaTable_Init_GerudoValley() {
|
|||||||
Entrance(COLOSSUS_GROTTO, {[]{return CanUse(SILVER_GAUNTLETS);}}),
|
Entrance(COLOSSUS_GROTTO, {[]{return CanUse(SILVER_GAUNTLETS);}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[COLOSSUS_GREAT_FAIRY_FOUNTAIN] = Area("Colossus Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY] = Area("Desert Colossus From Spirit Entryway", "Desert Colossus", DESERT_COLOSSUS, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
|
//Locations
|
||||||
|
LocationAccess(SHEIK_AT_COLOSSUS, {[]{return true;}}),
|
||||||
|
}, {
|
||||||
|
//Exist
|
||||||
|
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
|
||||||
|
});
|
||||||
|
|
||||||
|
areaTable[COLOSSUS_GREAT_FAIRY_FOUNTAIN] = Area("Colossus Great Fairy Fountain", "Colossus Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(COLOSSUS_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
LocationAccess(COLOSSUS_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && CanTakeDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && CanTakeDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
||||||
@ -223,7 +230,7 @@ void AreaTable_Init_GerudoValley() {
|
|||||||
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
|
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[COLOSSUS_GROTTO] = Area("Colossus Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[COLOSSUS_GROTTO] = Area("Colossus Grotto", "Colossus Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||||
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||||
|
@ -39,7 +39,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
/*Glitched*/[]{return Sticks && IsChild && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
|
/*Glitched*/[]{return Sticks && IsChild && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[HF_SOUTHEAST_GROTTO] = Area("HF Southeast Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
areaTable[HF_SOUTHEAST_GROTTO] = Area("HF Southeast Grotto", "HF Southeast Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(HF_SOUTHEAST_GROTTO_CHEST, {[]{return true;}}),
|
LocationAccess(HF_SOUTHEAST_GROTTO_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(HF_SOUTHEAST_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
LocationAccess(HF_SOUTHEAST_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||||
@ -48,7 +48,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[HF_OPEN_GROTTO] = Area("HF Open Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
areaTable[HF_OPEN_GROTTO] = Area("HF Open Grotto", "HF Open Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(HF_OPEN_GROTTO_CHEST, {[]{return true;}}),
|
LocationAccess(HF_OPEN_GROTTO_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(HF_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
LocationAccess(HF_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||||
@ -57,7 +57,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[HF_INSIDE_FENCE_GROTTO] = Area("HF Inside Fence Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[HF_INSIDE_FENCE_GROTTO] = Area("HF Inside Fence Grotto", "HF Inside Fence Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(HF_DEKU_SCRUB_GROTTO, {[]{return CanStunDeku;}}),
|
LocationAccess(HF_DEKU_SCRUB_GROTTO, {[]{return CanStunDeku;}}),
|
||||||
}, {
|
}, {
|
||||||
@ -65,7 +65,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[HF_COW_GROTTO] = Area("HF Cow Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
areaTable[HF_COW_GROTTO] = Area("HF Cow Grotto", "HF Cow Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(HF_GS_COW_GROTTO, {[]{return HasFireSource && HookshotOrBoomerang;},
|
LocationAccess(HF_GS_COW_GROTTO, {[]{return HasFireSource && HookshotOrBoomerang;},
|
||||||
/*Glitched*/[]{return (CanUse(STICKS) && Bombs && CanSurviveDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) && HookshotOrBoomerang;}}),
|
/*Glitched*/[]{return (CanUse(STICKS) && Bombs && CanSurviveDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) && HookshotOrBoomerang;}}),
|
||||||
@ -79,7 +79,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[HF_NEAR_MARKET_GROTTO] = Area("HF Near Market Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
areaTable[HF_NEAR_MARKET_GROTTO] = Area("HF Near Market Grotto", "HF Near Market Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(HF_NEAR_MARKET_GROTTO_CHEST, {[]{return true;}}),
|
LocationAccess(HF_NEAR_MARKET_GROTTO_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
LocationAccess(HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||||
@ -88,7 +88,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[HF_FAIRY_GROTTO] = Area("HF Fairy Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[HF_FAIRY_GROTTO] = Area("HF Fairy Grotto", "HF Fairy Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||||
}, {}, {
|
}, {}, {
|
||||||
@ -96,7 +96,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[HF_NEAR_KAK_GROTTO] = Area("HF Near Kak Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[HF_NEAR_KAK_GROTTO] = Area("HF Near Kak Grotto", "HF Near Kak Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(HF_GS_NEAR_KAK_GROTTO, {[]{return HookshotOrBoomerang;}}),
|
LocationAccess(HF_GS_NEAR_KAK_GROTTO, {[]{return HookshotOrBoomerang;}}),
|
||||||
}, {
|
}, {
|
||||||
@ -104,7 +104,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[HF_TEKTITE_GROTTO] = Area("HF Tektite Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[HF_TEKTITE_GROTTO] = Area("HF Tektite Grotto", "HF Tektite Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(HF_TEKTITE_GROTTO_FREESTANDING_POH, {[]{return ProgressiveScale >= 2 || CanUse(IRON_BOOTS);}}),
|
LocationAccess(HF_TEKTITE_GROTTO_FREESTANDING_POH, {[]{return ProgressiveScale >= 2 || CanUse(IRON_BOOTS);}}),
|
||||||
}, {
|
}, {
|
||||||
@ -163,7 +163,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[LH_LAB] = Area("LH Lab", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[LH_LAB] = Area("LH Lab", "LH Lab", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&EyedropsAccess, {[]{return EyedropsAccess || (IsAdult && (EyeballFrogAccess || (EyeballFrog && DisableTradeRevert)));}}),
|
EventAccess(&EyedropsAccess, {[]{return EyedropsAccess || (IsAdult && (EyeballFrogAccess || (EyeballFrog && DisableTradeRevert)));}}),
|
||||||
}, {
|
}, {
|
||||||
@ -182,7 +182,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(LAKE_HYLIA, {[]{return true;}}),
|
Entrance(LAKE_HYLIA, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[LH_FISHING_HOLE] = Area("LH Fishing Hole", "", NONE, DAY_NIGHT_CYCLE, {}, {
|
areaTable[LH_FISHING_HOLE] = Area("LH Fishing Hole", "LH Fishing Hole", NONE, DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(LH_CHILD_FISHING, {[]{return IsChild;}}),
|
LocationAccess(LH_CHILD_FISHING, {[]{return IsChild;}}),
|
||||||
LocationAccess(LH_ADULT_FISHING, {[]{return IsAdult;}}),
|
LocationAccess(LH_ADULT_FISHING, {[]{return IsAdult;}}),
|
||||||
@ -191,7 +191,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(LH_FISHING_ISLAND, {[]{return true;}}),
|
Entrance(LH_FISHING_ISLAND, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[LH_GROTTO] = Area("LH Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[LH_GROTTO] = Area("LH Grotto", "LH Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(LH_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
|
LocationAccess(LH_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
|
||||||
LocationAccess(LH_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
|
LocationAccess(LH_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
|
||||||
@ -224,7 +224,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(LLR_GROTTO, {[]{return IsChild;}}),
|
Entrance(LLR_GROTTO, {[]{return IsChild;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[LLR_TALONS_HOUSE] = Area("LLR Talons House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[LLR_TALONS_HOUSE] = Area("LLR Talons House", "LLR Talons House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(LLR_TALONS_CHICKENS, {[]{return IsChild && AtDay && ZeldasLetter;}}),
|
LocationAccess(LLR_TALONS_CHICKENS, {[]{return IsChild && AtDay && ZeldasLetter;}}),
|
||||||
}, {
|
}, {
|
||||||
@ -232,7 +232,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(LON_LON_RANCH, {[]{return true;}}),
|
Entrance(LON_LON_RANCH, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[LLR_STABLES] = Area("LLR Stables", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[LLR_STABLES] = Area("LLR Stables", "LLR Stables", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(LLR_STABLES_LEFT_COW, {[]{return CanPlay(EponasSong);},
|
LocationAccess(LLR_STABLES_LEFT_COW, {[]{return CanPlay(EponasSong);},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE))) && EponasSong;}}),
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE))) && EponasSong;}}),
|
||||||
@ -243,7 +243,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(LON_LON_RANCH, {[]{return true;}}),
|
Entrance(LON_LON_RANCH, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[LLR_TOWER] = Area("LLR Tower", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[LLR_TOWER] = Area("LLR Tower", "LLR Tower", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(LLR_FREESTANDING_POH, {[]{return IsChild;}}),
|
LocationAccess(LLR_FREESTANDING_POH, {[]{return IsChild;}}),
|
||||||
LocationAccess(LLR_TOWER_LEFT_COW, {[]{return CanPlay(EponasSong);},
|
LocationAccess(LLR_TOWER_LEFT_COW, {[]{return CanPlay(EponasSong);},
|
||||||
@ -255,7 +255,7 @@ void AreaTable_Init_HyruleField() {
|
|||||||
Entrance(LON_LON_RANCH, {[]{return true;}}),
|
Entrance(LON_LON_RANCH, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[LLR_GROTTO] = Area("LLR Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[LLR_GROTTO] = Area("LLR Grotto", "LLR Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(LLR_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
|
LocationAccess(LLR_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
|
||||||
LocationAccess(LLR_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
|
LocationAccess(LLR_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
|
||||||
|
@ -23,8 +23,6 @@ void AreaTable_Init_Kakariko() {
|
|||||||
LocationAccess(KAK_GS_TREE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
|
LocationAccess(KAK_GS_TREE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
|
||||||
LocationAccess(KAK_GS_WATCHTOWER, {[]{return IsChild && (Slingshot || HasBombchus || CanUse(BOW) || CanUse(LONGSHOT)) && AtNight && CanGetNightTimeGS;},
|
LocationAccess(KAK_GS_WATCHTOWER, {[]{return IsChild && (Slingshot || HasBombchus || CanUse(BOW) || CanUse(LONGSHOT)) && AtNight && CanGetNightTimeGS;},
|
||||||
/*Glitched*/[]{return IsChild && AtNight && CanGetNightTimeGS && (CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::SuperStab, GlitchDifficulty::NOVICE) || (Sticks && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE)));}}),
|
/*Glitched*/[]{return IsChild && AtNight && CanGetNightTimeGS && (CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::SuperStab, GlitchDifficulty::NOVICE) || (Sticks && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE)));}}),
|
||||||
LocationAccess(KAK_GS_ABOVE_IMPAS_HOUSE, {[]{return IsAdult && CanUse(HOOKSHOT) && AtNight && CanGetNightTimeGS;},
|
|
||||||
/*Glitched*/[]{return IsAdult && AtNight && CanGetNightTimeGS && ((HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE));}}),
|
|
||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||||
@ -45,6 +43,8 @@ void AreaTable_Init_Kakariko() {
|
|||||||
/*Glitched*/[]{return IsAdult && ((HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE));}}),
|
/*Glitched*/[]{return IsAdult && ((HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE));}}),
|
||||||
Entrance(KAK_ROOFTOP, {[]{return CanUse(HOOKSHOT) || (LogicManOnRoof && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(BOW) || CanUse(LONGSHOT)));},
|
Entrance(KAK_ROOFTOP, {[]{return CanUse(HOOKSHOT) || (LogicManOnRoof && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(BOW) || CanUse(LONGSHOT)));},
|
||||||
/*Glitched*/[]{return LogicManOnRoof && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE);}}),
|
/*Glitched*/[]{return LogicManOnRoof && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE);}}),
|
||||||
|
Entrance(KAK_IMPAS_ROOFTOP, {[]{return CanUse(HOOKSHOT);},
|
||||||
|
/*Glitched*/[]{return (HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE);}}),
|
||||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||||
Entrance(KAK_BEHIND_GATE, {[]{return IsAdult || (KakarikoVillageGateOpen);},
|
Entrance(KAK_BEHIND_GATE, {[]{return IsAdult || (KakarikoVillageGateOpen);},
|
||||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||||
@ -56,6 +56,15 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
areaTable[KAK_IMPAS_ROOFTOP] = Area("Kak Impas Rooftop", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
|
//Locations
|
||||||
|
LocationAccess(KAK_GS_ABOVE_IMPAS_HOUSE, {[]{return IsAdult && AtNight && CanGetNightTimeGS && (CanJumpslash || CanUseProjectile);}}),
|
||||||
|
}, {
|
||||||
|
//Exits
|
||||||
|
Entrance(KAK_IMPAS_LEDGE, {[]{return true;}}),
|
||||||
|
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||||
|
});
|
||||||
|
|
||||||
areaTable[KAK_ROOFTOP] = Area("Kak Rooftop", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KAK_ROOFTOP] = Area("Kak Rooftop", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KAK_MAN_ON_ROOF, {[]{return true;}}),
|
LocationAccess(KAK_MAN_ON_ROOF, {[]{return true;}}),
|
||||||
@ -73,7 +82,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::NOVICE);}}),
|
/*Glitched*/[]{return CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::NOVICE);}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_CARPENTER_BOSS_HOUSE] = Area("Kak Carpenter Boss House", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[KAK_CARPENTER_BOSS_HOUSE] = Area("Kak Carpenter Boss House", "Kak Carpenter Boss House", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&WakeUpAdultTalon, {[]{return WakeUpAdultTalon || (IsAdult && PocketEgg);}}),
|
EventAccess(&WakeUpAdultTalon, {[]{return WakeUpAdultTalon || (IsAdult && PocketEgg);}}),
|
||||||
}, {}, {
|
}, {}, {
|
||||||
@ -81,7 +90,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_HOUSE_OF_SKULLTULA] = Area("Kak House of Skulltula", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KAK_HOUSE_OF_SKULLTULA] = Area("Kak House of Skulltula", "Kak House of Skulltula", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KAK_10_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 10;}}),
|
LocationAccess(KAK_10_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 10;}}),
|
||||||
LocationAccess(KAK_20_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 20;}}),
|
LocationAccess(KAK_20_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 20;}}),
|
||||||
@ -93,13 +102,13 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_IMPAS_HOUSE] = Area("Kak Impas House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[KAK_IMPAS_HOUSE] = Area("Kak Impas House", "Kak Impas House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
|
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
|
||||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_IMPAS_HOUSE_BACK] = Area("Kak Impas House Back", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KAK_IMPAS_HOUSE_BACK] = Area("Kak Impas House Back", "Kak Impas House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KAK_IMPAS_HOUSE_FREESTANDING_POH, {[]{return true;}}),
|
LocationAccess(KAK_IMPAS_HOUSE_FREESTANDING_POH, {[]{return true;}}),
|
||||||
}, {
|
}, {
|
||||||
@ -108,13 +117,13 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
|
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_IMPAS_HOUSE_NEAR_COW] = Area("Kak Impas House Near Cow", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KAK_IMPAS_HOUSE_NEAR_COW] = Area("Kak Impas House Near Cow", "Kak Impas House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KAK_IMPAS_HOUSE_COW, {[]{return CanPlay(EponasSong);},
|
LocationAccess(KAK_IMPAS_HOUSE_COW, {[]{return CanPlay(EponasSong);},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED))) && EponasSong;}}),
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED))) && EponasSong;}}),
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
areaTable[KAK_WINDMILL] = Area("Kak Windmill", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[KAK_WINDMILL] = Area("Kak Windmill", "Windmill and Dampes Grave", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&DrainWell, {[]{return DrainWell || (IsChild && CanPlay(SongOfStorms));},
|
EventAccess(&DrainWell, {[]{return DrainWell || (IsChild && CanPlay(SongOfStorms));},
|
||||||
/*Glitched*/[]{return IsChild && SongOfStorms && (CanDoGlitch(GlitchType::WindmillBombOI, GlitchDifficulty::ADVANCED) || ((Fish || Bugs) && CanShield && ((Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2))) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) &&
|
/*Glitched*/[]{return IsChild && SongOfStorms && (CanDoGlitch(GlitchType::WindmillBombOI, GlitchDifficulty::ADVANCED) || ((Fish || Bugs) && CanShield && ((Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2))) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) &&
|
||||||
@ -131,7 +140,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_BAZAAR] = Area("Kak Bazaar", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KAK_BAZAAR] = Area("Kak Bazaar", "Kak Bazaar", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KAK_BAZAAR_ITEM_1, {[]{return true;}}),
|
LocationAccess(KAK_BAZAAR_ITEM_1, {[]{return true;}}),
|
||||||
LocationAccess(KAK_BAZAAR_ITEM_2, {[]{return true;}}),
|
LocationAccess(KAK_BAZAAR_ITEM_2, {[]{return true;}}),
|
||||||
@ -146,7 +155,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_SHOOTING_GALLERY] = Area("Kak Shooting Gallery", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KAK_SHOOTING_GALLERY] = Area("Kak Shooting Gallery", "Kak Shooting Gallery", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KAK_SHOOTING_GALLERY_REWARD, {[]{return IsAdult && Bow;}}),
|
LocationAccess(KAK_SHOOTING_GALLERY_REWARD, {[]{return IsAdult && Bow;}}),
|
||||||
}, {
|
}, {
|
||||||
@ -154,7 +163,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_POTION_SHOP_FRONT] = Area("Kak Potion Shop Front", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KAK_POTION_SHOP_FRONT] = Area("Kak Potion Shop Front", "Kak Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KAK_POTION_SHOP_ITEM_1, {[]{return IsAdult;}}),
|
LocationAccess(KAK_POTION_SHOP_ITEM_1, {[]{return IsAdult;}}),
|
||||||
LocationAccess(KAK_POTION_SHOP_ITEM_2, {[]{return IsAdult;}}),
|
LocationAccess(KAK_POTION_SHOP_ITEM_2, {[]{return IsAdult;}}),
|
||||||
@ -170,13 +179,13 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(KAK_POTION_SHOP_BACK, {[]{return IsAdult;}}),
|
Entrance(KAK_POTION_SHOP_BACK, {[]{return IsAdult;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_POTION_SHOP_BACK] = Area("Kak Potion Shop Back", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[KAK_POTION_SHOP_BACK] = Area("Kak Potion Shop Back", "Kak Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(KAK_BACKYARD, {[]{return IsAdult;}}),
|
Entrance(KAK_BACKYARD, {[]{return IsAdult;}}),
|
||||||
Entrance(KAK_POTION_SHOP_FRONT, {[]{return true;}}),
|
Entrance(KAK_POTION_SHOP_FRONT, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_ODD_POTION_BUILDING] = Area("Kak Granny's Potion Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[KAK_ODD_POTION_BUILDING] = Area("Kak Granny's Potion Shop", "Kak Granny's Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&OddPoulticeAccess, {[]{return OddPoulticeAccess || (IsAdult && (OddMushroomAccess || (OddMushroom && DisableTradeRevert)));}}),
|
EventAccess(&OddPoulticeAccess, {[]{return OddPoulticeAccess || (IsAdult && (OddMushroomAccess || (OddMushroom && DisableTradeRevert)));}}),
|
||||||
}, {
|
}, {
|
||||||
@ -186,7 +195,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(KAK_BACKYARD, {[]{return true;}}),
|
Entrance(KAK_BACKYARD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_REDEAD_GROTTO] = Area("Kak Redead Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KAK_REDEAD_GROTTO] = Area("Kak Redead Grotto", "Kak Redead Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KAK_REDEAD_GROTTO_CHEST, {[]{return IsAdult || (Sticks || KokiriSword || CanUse(DINS_FIRE) || CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD));}}),
|
LocationAccess(KAK_REDEAD_GROTTO_CHEST, {[]{return IsAdult || (Sticks || KokiriSword || CanUse(DINS_FIRE) || CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD));}}),
|
||||||
}, {
|
}, {
|
||||||
@ -194,7 +203,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KAK_OPEN_GROTTO] = Area("Kak Open Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
areaTable[KAK_OPEN_GROTTO] = Area("Kak Open Grotto", "Kak Open Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KAK_OPEN_GROTTO_CHEST, {[]{return true;}}),
|
LocationAccess(KAK_OPEN_GROTTO_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(KAK_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
LocationAccess(KAK_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||||
@ -230,7 +239,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HookshotJump_Bonk, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::NOVICE);}}),
|
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HookshotJump_Bonk, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::NOVICE);}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GRAVEYARD_SHIELD_GRAVE] = Area("Graveyard Shield Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[GRAVEYARD_SHIELD_GRAVE] = Area("Graveyard Shield Grave", "Graveyard Shield Grave", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(GRAVEYARD_SHIELD_GRAVE_CHEST, {[]{return true;}}),
|
LocationAccess(GRAVEYARD_SHIELD_GRAVE_CHEST, {[]{return true;}}),
|
||||||
//Free Fairies
|
//Free Fairies
|
||||||
@ -239,7 +248,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GRAVEYARD_HEART_PIECE_GRAVE] = Area("Graveyard Heart Piece Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[GRAVEYARD_HEART_PIECE_GRAVE] = Area("Graveyard Heart Piece Grave", "Graveyard Heart Piece Grave", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(GRAVEYARD_HEART_PIECE_GRAVE_CHEST, {[]{return CanPlay(SunsSong);},
|
LocationAccess(GRAVEYARD_HEART_PIECE_GRAVE_CHEST, {[]{return CanPlay(SunsSong);},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) || ((Bugs || Fish) && CanShield && (Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2))) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SunsSong;}}),
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) || ((Bugs || Fish) && CanShield && (Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2))) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SunsSong;}}),
|
||||||
@ -248,7 +257,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GRAVEYARD_COMPOSERS_GRAVE] = Area("Graveyard Composers Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[GRAVEYARD_COMPOSERS_GRAVE] = Area("Graveyard Composers Grave", "Graveyard Composers Grave", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(GRAVEYARD_COMPOSERS_GRAVE_CHEST, {[]{return HasFireSource;},
|
LocationAccess(GRAVEYARD_COMPOSERS_GRAVE_CHEST, {[]{return HasFireSource;},
|
||||||
/*Glitched*/[]{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE);}}),
|
/*Glitched*/[]{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE);}}),
|
||||||
@ -258,7 +267,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GRAVEYARD_DAMPES_GRAVE] = Area("Graveyard Dampes Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[GRAVEYARD_DAMPES_GRAVE] = Area("Graveyard Dampes Grave", "Windmill and Dampes Grave", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&NutPot, {[]{return true;}}),
|
EventAccess(&NutPot, {[]{return true;}}),
|
||||||
EventAccess(&DampesWindmillAccess, {[]{return DampesWindmillAccess || (IsAdult && CanPlay(SongOfTime));},
|
EventAccess(&DampesWindmillAccess, {[]{return DampesWindmillAccess || (IsAdult && CanPlay(SongOfTime));},
|
||||||
@ -276,7 +285,7 @@ void AreaTable_Init_Kakariko() {
|
|||||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsAdult && SongOfTime;}}),
|
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsAdult && SongOfTime;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "Graveyard Dampes House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
@ -53,7 +53,7 @@ void AreaTable_Init_LostWoods() {
|
|||||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KF_LINKS_HOUSE] = Area("KF Link's House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KF_LINKS_HOUSE] = Area("KF Link's House", "KF Link's House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KF_LINKS_HOUSE_COW, {[]{return IsAdult && CanPlay(EponasSong) && LinksCow;},
|
LocationAccess(KF_LINKS_HOUSE_COW, {[]{return IsAdult && CanPlay(EponasSong) && LinksCow;},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (NumBottles >= 2 && Fairy)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::EXPERT))) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && Bombs && IsAdult && EponasSong && LinksCow;}}),
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (NumBottles >= 2 && Fairy)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::EXPERT))) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && Bombs && IsAdult && EponasSong && LinksCow;}}),
|
||||||
@ -62,7 +62,7 @@ void AreaTable_Init_LostWoods() {
|
|||||||
Entrance(KOKIRI_FOREST, {[]{return true;}})
|
Entrance(KOKIRI_FOREST, {[]{return true;}})
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KF_MIDOS_HOUSE] = Area("KF Mido's House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KF_MIDOS_HOUSE] = Area("KF Mido's House", "KF Mido's House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KF_MIDOS_TOP_LEFT_CHEST, {[]{return true;}}),
|
LocationAccess(KF_MIDOS_TOP_LEFT_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(KF_MIDOS_TOP_RIGHT_CHEST, {[]{return true;}}),
|
LocationAccess(KF_MIDOS_TOP_RIGHT_CHEST, {[]{return true;}}),
|
||||||
@ -73,22 +73,22 @@ void AreaTable_Init_LostWoods() {
|
|||||||
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KF_SARIAS_HOUSE] = Area("KF Saria's House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[KF_SARIAS_HOUSE] = Area("KF Saria's House", "KF Saria's House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KF_HOUSE_OF_TWINS] = Area("KF House of Twins", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[KF_HOUSE_OF_TWINS] = Area("KF House of Twins", "KF House of Twins", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KF_KNOW_IT_ALL_HOUSE] = Area("KF Know It All House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[KF_KNOW_IT_ALL_HOUSE] = Area("KF Know It All House", "KF Know It All House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KF_KOKIRI_SHOP] = Area("KF Kokiri Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[KF_KOKIRI_SHOP] = Area("KF Kokiri Shop", "KF Kokiri Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KF_SHOP_ITEM_1, {[]{return true;}}),
|
LocationAccess(KF_SHOP_ITEM_1, {[]{return true;}}),
|
||||||
LocationAccess(KF_SHOP_ITEM_2, {[]{return true;}}),
|
LocationAccess(KF_SHOP_ITEM_2, {[]{return true;}}),
|
||||||
@ -103,7 +103,7 @@ void AreaTable_Init_LostWoods() {
|
|||||||
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[KF_STORMS_GROTTO] = Area("KF Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
areaTable[KF_STORMS_GROTTO] = Area("KF Storms Grotto", "KF Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(KF_STORMS_GROTTO_CHEST, {[]{return true;}}),
|
LocationAccess(KF_STORMS_GROTTO_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(KF_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
LocationAccess(KF_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||||
@ -177,7 +177,7 @@ void AreaTable_Init_LostWoods() {
|
|||||||
/*Glitched*/[]{return Here(LW_BEYOND_MIDO, []{return IsChild && CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}}),
|
/*Glitched*/[]{return Here(LW_BEYOND_MIDO, []{return IsChild && CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[LW_NEAR_SHORTCUTS_GROTTO] = Area("LW Near Shortcuts Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
areaTable[LW_NEAR_SHORTCUTS_GROTTO] = Area("LW Near Shortcuts Grotto", "LW Near Shortcuts Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_CHEST, {[]{return true;}}),
|
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||||
@ -186,7 +186,7 @@ void AreaTable_Init_LostWoods() {
|
|||||||
Entrance(THE_LOST_WOODS, {[]{return true;}}),
|
Entrance(THE_LOST_WOODS, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[DEKU_THEATER] = Area("Deku Theater", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[DEKU_THEATER] = Area("Deku Theater", "Deku Theater", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(DEKU_THEATER_SKULL_MASK, {[]{return IsChild && SkullMask;}}),
|
LocationAccess(DEKU_THEATER_SKULL_MASK, {[]{return IsChild && SkullMask;}}),
|
||||||
LocationAccess(DEKU_THEATER_MASK_OF_TRUTH, {[]{return IsChild && MaskOfTruth;}}),
|
LocationAccess(DEKU_THEATER_MASK_OF_TRUTH, {[]{return IsChild && MaskOfTruth;}}),
|
||||||
@ -195,7 +195,7 @@ void AreaTable_Init_LostWoods() {
|
|||||||
Entrance(LW_BEYOND_MIDO, {[]{return true;}}),
|
Entrance(LW_BEYOND_MIDO, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[LW_SCRUBS_GROTTO] = Area("LW Scrubs Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[LW_SCRUBS_GROTTO] = Area("LW Scrubs Grotto", "LW Scrubs Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(LW_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
LocationAccess(LW_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||||
LocationAccess(LW_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
LocationAccess(LW_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||||
@ -232,7 +232,7 @@ void AreaTable_Init_LostWoods() {
|
|||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[SFM_FAIRY_GROTTO] = Area("SFM Fairy Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[SFM_FAIRY_GROTTO] = Area("SFM Fairy Grotto", "SFM Fairy Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||||
}, {}, {
|
}, {}, {
|
||||||
@ -240,7 +240,7 @@ void AreaTable_Init_LostWoods() {
|
|||||||
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
|
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[SFM_WOLFOS_GROTTO] = Area("SFM Wolfos Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[SFM_WOLFOS_GROTTO] = Area("SFM Wolfos Grotto", "SFM Wolfos Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(SFM_WOLFOS_GROTTO_CHEST, {[]{return IsAdult || Slingshot || Sticks || KokiriSword || CanUse(DINS_FIRE) || CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);}}),
|
LocationAccess(SFM_WOLFOS_GROTTO_CHEST, {[]{return IsAdult || Slingshot || Sticks || KokiriSword || CanUse(DINS_FIRE) || CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);}}),
|
||||||
}, {
|
}, {
|
||||||
@ -248,7 +248,7 @@ void AreaTable_Init_LostWoods() {
|
|||||||
Entrance(SFM_ENTRYWAY, {[]{return true;}}),
|
Entrance(SFM_ENTRYWAY, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[SFM_STORMS_GROTTO] = Area("SFM Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[SFM_STORMS_GROTTO] = Area("SFM Storms Grotto", "SFM Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(SFM_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
LocationAccess(SFM_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||||
LocationAccess(SFM_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
LocationAccess(SFM_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||||
|
@ -14,7 +14,7 @@ void AreaTable_Init_SpiritTemple() {
|
|||||||
//Exits
|
//Exits
|
||||||
Entrance(SPIRIT_TEMPLE_LOBBY, {[]{return Dungeon::SpiritTemple.IsVanilla();}}),
|
Entrance(SPIRIT_TEMPLE_LOBBY, {[]{return Dungeon::SpiritTemple.IsVanilla();}}),
|
||||||
Entrance(SPIRIT_TEMPLE_MQ_LOBBY, {[]{return Dungeon::SpiritTemple.IsMQ();}}),
|
Entrance(SPIRIT_TEMPLE_MQ_LOBBY, {[]{return Dungeon::SpiritTemple.IsMQ();}}),
|
||||||
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
|
Entrance(DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
/*--------------------------
|
/*--------------------------
|
||||||
|
@ -76,7 +76,7 @@ void AreaTable_Init_ZorasDomain() {
|
|||||||
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
|
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[ZR_OPEN_GROTTO] = Area("ZR Open Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
areaTable[ZR_OPEN_GROTTO] = Area("ZR Open Grotto", "ZR Open Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(ZR_OPEN_GROTTO_CHEST, {[]{return true;}}),
|
LocationAccess(ZR_OPEN_GROTTO_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(ZR_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
LocationAccess(ZR_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||||
@ -85,7 +85,7 @@ void AreaTable_Init_ZorasDomain() {
|
|||||||
Entrance(ZORAS_RIVER, {[]{return true;}}),
|
Entrance(ZORAS_RIVER, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[ZR_FAIRY_GROTTO] = Area("ZR Fairy Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[ZR_FAIRY_GROTTO] = Area("ZR Fairy Grotto", "ZR Fairy Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Event
|
//Event
|
||||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||||
}, {}, {
|
}, {}, {
|
||||||
@ -93,7 +93,7 @@ void AreaTable_Init_ZorasDomain() {
|
|||||||
Entrance(ZORAS_RIVER, {[]{return true;}}),
|
Entrance(ZORAS_RIVER, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[ZR_STORMS_GROTTO] = Area("ZR Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[ZR_STORMS_GROTTO] = Area("ZR Storms Grotto", "ZR Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(ZR_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
LocationAccess(ZR_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||||
LocationAccess(ZR_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
LocationAccess(ZR_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||||
@ -142,7 +142,7 @@ void AreaTable_Init_ZorasDomain() {
|
|||||||
Entrance(ZORAS_FOUNTAIN, {[]{return true;}}),
|
Entrance(ZORAS_FOUNTAIN, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[ZD_SHOP] = Area("ZD Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[ZD_SHOP] = Area("ZD Shop", "ZD Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(ZD_SHOP_ITEM_1, {[]{return true;}}),
|
LocationAccess(ZD_SHOP_ITEM_1, {[]{return true;}}),
|
||||||
LocationAccess(ZD_SHOP_ITEM_2, {[]{return true;}}),
|
LocationAccess(ZD_SHOP_ITEM_2, {[]{return true;}}),
|
||||||
@ -157,7 +157,7 @@ void AreaTable_Init_ZorasDomain() {
|
|||||||
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
|
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[ZD_STORMS_GROTTO] = Area("ZD Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
areaTable[ZD_STORMS_GROTTO] = Area("ZD Storms Grotto", "ZD Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||||
//Events
|
//Events
|
||||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||||
}, {}, {
|
}, {}, {
|
||||||
@ -191,7 +191,7 @@ void AreaTable_Init_ZorasDomain() {
|
|||||||
/*Glitched*/[]{return IsChild && (KokiriSword || Sticks) && CanShield && (CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::ADVANCED) || (CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::INTERMEDIATE)));}}),
|
/*Glitched*/[]{return IsChild && (KokiriSword || Sticks) && CanShield && (CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::ADVANCED) || (CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::INTERMEDIATE)));}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[ZF_GREAT_FAIRY_FOUNTAIN] = Area("ZF Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[ZF_GREAT_FAIRY_FOUNTAIN] = Area("ZF Great Fairy Fountain", "ZF Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(ZF_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
LocationAccess(ZF_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||||
|
@ -194,6 +194,52 @@ string_view grottoEntrancesDesc = "Shuffle the pool of grotto entrances, i
|
|||||||
"all graves, small Fairy Fountains and the Lost\n" //
|
"all graves, small Fairy Fountains and the Lost\n" //
|
||||||
"Woods Stage."; //
|
"Woods Stage."; //
|
||||||
/*------------------------------ //
|
/*------------------------------ //
|
||||||
|
| OWL DROPS | //
|
||||||
|
------------------------------*/ //
|
||||||
|
string_view owlDropsDesc = "Randomize where Kaepora Gaebora (the Owl) drops\n"//
|
||||||
|
"you at when you talk to him at Lake Hylia or at\n"//
|
||||||
|
"the top of Death Mountain Trail."; //
|
||||||
|
/*------------------------------ //
|
||||||
|
| WARP SONGS | //
|
||||||
|
------------------------------*/ //
|
||||||
|
string_view warpSongsDesc = "Randomize where each of the 6 warp songs leads to.";
|
||||||
|
//
|
||||||
|
/*------------------------------ //
|
||||||
|
| OVERWORLD SPAWNS | //
|
||||||
|
------------------------------*/ //
|
||||||
|
string_view overworldSpawnsDesc = "Randomize where you start as Child or Adult when\n"
|
||||||
|
"loading a save in the Overworld. This means you\n"//
|
||||||
|
"may not necessarily spawn inside Link's House or\n"
|
||||||
|
"Temple of Time.\n" //
|
||||||
|
"\n" //
|
||||||
|
"This stays consistent after saving and loading the"
|
||||||
|
"game again."; //
|
||||||
|
/*------------------------------ //
|
||||||
|
| MIXED ENTRANCE POOLS | //
|
||||||
|
------------------------------*/ //
|
||||||
|
string_view mixedPoolsDesc = "Shuffle entrances into a mixed pool instead of\n" //
|
||||||
|
"separate ones. For example, enabling the settings\n"
|
||||||
|
"to shuffle grotto, dungeon, and overworld\n" //
|
||||||
|
"entrances and selecting grotto and dungeon\n" //
|
||||||
|
"entrances here will allow a dungeon to be inside a"
|
||||||
|
"grotto or vice versa, while overworld entrances\n"//
|
||||||
|
"are shuffled in their own separate pool and\n" //
|
||||||
|
"indoors stay vanilla."; //
|
||||||
|
string_view mixDungeonsDesc = "Dungeon entrances will be part of the mixed pool.";
|
||||||
|
string_view mixOverworldDesc = "Overworld entrances will be part of the mixed\n" //
|
||||||
|
"pool."; //
|
||||||
|
string_view mixInteriorsDesc = "Interior entrances will be part of the mixed pool.";
|
||||||
|
string_view mixGrottosDesc = "Grotto entrances will be part of the mixed pool.";//
|
||||||
|
/*------------------------------ //
|
||||||
|
| DECOUPLED ENTRANCES | //
|
||||||
|
------------------------------*/ //
|
||||||
|
string_view decoupledEntrancesDesc = "Decouple entrances when shuffling them. This means"
|
||||||
|
"you are no longer guaranteed to end up back where "
|
||||||
|
"you came from when you go back through an\n" //
|
||||||
|
"entrance. This also adds the one-way entrance from"
|
||||||
|
"Gerudo Valley to Lake Hylia in the pool of\n" //
|
||||||
|
"overworld entrances when they are shuffled."; //
|
||||||
|
/*------------------------------ //
|
||||||
| BOMBCHUS IN LOGIC | //
|
| BOMBCHUS IN LOGIC | //
|
||||||
------------------------------*/ //
|
------------------------------*/ //
|
||||||
string_view bombchuLogicDesc = "Bombchus are properly considered in logic.\n" //
|
string_view bombchuLogicDesc = "Bombchus are properly considered in logic.\n" //
|
||||||
|
@ -61,6 +61,20 @@ extern string_view overworldEntrancesDesc;
|
|||||||
|
|
||||||
extern string_view grottoEntrancesDesc;
|
extern string_view grottoEntrancesDesc;
|
||||||
|
|
||||||
|
extern string_view owlDropsDesc;
|
||||||
|
|
||||||
|
extern string_view warpSongsDesc;
|
||||||
|
|
||||||
|
extern string_view overworldSpawnsDesc;
|
||||||
|
|
||||||
|
extern string_view mixedPoolsDesc;
|
||||||
|
extern string_view mixDungeonsDesc;
|
||||||
|
extern string_view mixOverworldDesc;
|
||||||
|
extern string_view mixInteriorsDesc;
|
||||||
|
extern string_view mixGrottosDesc;
|
||||||
|
|
||||||
|
extern string_view decoupledEntrancesDesc;
|
||||||
|
|
||||||
extern string_view interiorEntrancesOff;
|
extern string_view interiorEntrancesOff;
|
||||||
extern string_view interiorEntrancesSimple;
|
extern string_view interiorEntrancesSimple;
|
||||||
extern string_view interiorEntrancesAll;
|
extern string_view interiorEntrancesAll;
|
||||||
|
@ -92,6 +92,15 @@ namespace Settings {
|
|||||||
Option ShuffleOverworldEntrances = Option::Bool("Overworld Entrances", {"Off", "On"}, {overworldEntrancesDesc});
|
Option ShuffleOverworldEntrances = Option::Bool("Overworld Entrances", {"Off", "On"}, {overworldEntrancesDesc});
|
||||||
Option ShuffleInteriorEntrances = Option::U8 ("Interior Entrances", {"Off", "Simple", "All"}, {interiorEntrancesOff, interiorEntrancesSimple, interiorEntrancesAll});
|
Option ShuffleInteriorEntrances = Option::U8 ("Interior Entrances", {"Off", "Simple", "All"}, {interiorEntrancesOff, interiorEntrancesSimple, interiorEntrancesAll});
|
||||||
Option ShuffleGrottoEntrances = Option::Bool("Grottos Entrances", {"Off", "On"}, {grottoEntrancesDesc});
|
Option ShuffleGrottoEntrances = Option::Bool("Grottos Entrances", {"Off", "On"}, {grottoEntrancesDesc});
|
||||||
|
Option ShuffleOwlDrops = Option::Bool("Owl Drops", {"Off", "On"}, {owlDropsDesc});
|
||||||
|
Option ShuffleWarpSongs = Option::Bool("Warp Songs", {"Off", "On"}, {warpSongsDesc});
|
||||||
|
Option ShuffleOverworldSpawns = Option::Bool("Overworld Spawns", {"Off", "On"}, {overworldSpawnsDesc});
|
||||||
|
Option MixedEntrancePools = Option::Bool("Mixed Entrance Pools", {"Off", "On"}, {mixedPoolsDesc});
|
||||||
|
Option MixDungeons = Option::Bool("Mix Dungeons", {"Off", "On"}, {mixDungeonsDesc});
|
||||||
|
Option MixOverworld = Option::Bool("Mix Overworld", {"Off", "On"}, {mixOverworldDesc});
|
||||||
|
Option MixInteriors = Option::Bool("Mix Interiors", {"Off", "On"}, {mixInteriorsDesc});
|
||||||
|
Option MixGrottos = Option::Bool("Mix Grottos", {"Off", "On"}, {mixGrottosDesc});
|
||||||
|
Option DecoupleEntrances = Option::Bool("Decouple Entrances", {"Off", "On"}, {decoupledEntrancesDesc});
|
||||||
Option BombchusInLogic = Option::Bool("Bombchus in Logic", {"Off", "On"}, {bombchuLogicDesc});
|
Option BombchusInLogic = Option::Bool("Bombchus in Logic", {"Off", "On"}, {bombchuLogicDesc});
|
||||||
Option AmmoDrops = Option::U8 ("Ammo Drops", {"On", "On + Bombchu", "Off"}, {defaultAmmoDropsDesc, bombchuDropsDesc, noAmmoDropsDesc}, OptionCategory::Setting, AMMODROPS_BOMBCHU);
|
Option AmmoDrops = Option::U8 ("Ammo Drops", {"On", "On + Bombchu", "Off"}, {defaultAmmoDropsDesc, bombchuDropsDesc, noAmmoDropsDesc}, OptionCategory::Setting, AMMODROPS_BOMBCHU);
|
||||||
Option HeartDropRefill = Option::U8 ("Heart Drops and Refills",{"On", "No Drop", "No Refill", "Off"}, {defaultHeartDropsDesc, noHeartDropsDesc, noHeartRefillDesc, scarceHeartsDesc}, OptionCategory::Setting, HEARTDROPREFILL_VANILLA);
|
Option HeartDropRefill = Option::U8 ("Heart Drops and Refills",{"On", "No Drop", "No Refill", "Off"}, {defaultHeartDropsDesc, noHeartDropsDesc, noHeartRefillDesc, scarceHeartsDesc}, OptionCategory::Setting, HEARTDROPREFILL_VANILLA);
|
||||||
@ -119,6 +128,15 @@ namespace Settings {
|
|||||||
&ShuffleOverworldEntrances,
|
&ShuffleOverworldEntrances,
|
||||||
&ShuffleInteriorEntrances,
|
&ShuffleInteriorEntrances,
|
||||||
&ShuffleGrottoEntrances,
|
&ShuffleGrottoEntrances,
|
||||||
|
&ShuffleOwlDrops,
|
||||||
|
&ShuffleWarpSongs,
|
||||||
|
&ShuffleOverworldSpawns,
|
||||||
|
&MixedEntrancePools,
|
||||||
|
&MixDungeons,
|
||||||
|
&MixOverworld,
|
||||||
|
&MixInteriors,
|
||||||
|
&MixGrottos,
|
||||||
|
&DecoupleEntrances,
|
||||||
&BombchusInLogic,
|
&BombchusInLogic,
|
||||||
&AmmoDrops,
|
&AmmoDrops,
|
||||||
&HeartDropRefill,
|
&HeartDropRefill,
|
||||||
@ -1256,6 +1274,15 @@ namespace Settings {
|
|||||||
ctx.shuffleOverworldEntrances = (ShuffleOverworldEntrances) ? 1 : 0;
|
ctx.shuffleOverworldEntrances = (ShuffleOverworldEntrances) ? 1 : 0;
|
||||||
ctx.shuffleInteriorEntrances = ShuffleInteriorEntrances.Value<uint8_t>();
|
ctx.shuffleInteriorEntrances = ShuffleInteriorEntrances.Value<uint8_t>();
|
||||||
ctx.shuffleGrottoEntrances = (ShuffleGrottoEntrances) ? 1 : 0;
|
ctx.shuffleGrottoEntrances = (ShuffleGrottoEntrances) ? 1 : 0;
|
||||||
|
ctx.shuffleOwlDrops = (ShuffleOwlDrops) ? 1 : 0;
|
||||||
|
ctx.shuffleWarpSongs = (ShuffleWarpSongs) ? 1 : 0;
|
||||||
|
ctx.shuffleOverworldSpawns = (ShuffleOverworldSpawns) ? 1 : 0;
|
||||||
|
ctx.mixedEntrancePools = (MixedEntrancePools) ? 1 : 0;
|
||||||
|
ctx.mixDungeons = (MixDungeons) ? 1 : 0;
|
||||||
|
ctx.mixOverworld = (MixOverworld) ? 1 : 0;
|
||||||
|
ctx.mixInteriors = (MixInteriors) ? 1 : 0;
|
||||||
|
ctx.mixGrottos = (MixGrottos) ? 1 : 0;
|
||||||
|
ctx.decoupleEntrances = (DecoupleEntrances) ? 1 : 0;
|
||||||
ctx.bombchusInLogic = (BombchusInLogic) ? 1 : 0;
|
ctx.bombchusInLogic = (BombchusInLogic) ? 1 : 0;
|
||||||
ctx.ammoDrops = AmmoDrops.Value<uint8_t>();
|
ctx.ammoDrops = AmmoDrops.Value<uint8_t>();
|
||||||
ctx.heartDropRefill = HeartDropRefill.Value<uint8_t>();
|
ctx.heartDropRefill = HeartDropRefill.Value<uint8_t>();
|
||||||
@ -1929,6 +1956,11 @@ namespace Settings {
|
|||||||
ShuffleOverworldEntrances.Unhide();
|
ShuffleOverworldEntrances.Unhide();
|
||||||
ShuffleInteriorEntrances.Unhide();
|
ShuffleInteriorEntrances.Unhide();
|
||||||
ShuffleGrottoEntrances.Unhide();
|
ShuffleGrottoEntrances.Unhide();
|
||||||
|
ShuffleOwlDrops.Unhide();
|
||||||
|
ShuffleWarpSongs.Unhide();
|
||||||
|
ShuffleOverworldSpawns.Unhide();
|
||||||
|
MixedEntrancePools.Unhide();
|
||||||
|
DecoupleEntrances.Unhide();
|
||||||
} else {
|
} else {
|
||||||
ShuffleDungeonEntrances.SetSelectedIndex(SHUFFLEDUNGEONS_OFF);
|
ShuffleDungeonEntrances.SetSelectedIndex(SHUFFLEDUNGEONS_OFF);
|
||||||
ShuffleDungeonEntrances.Hide();
|
ShuffleDungeonEntrances.Hide();
|
||||||
@ -1938,6 +1970,56 @@ namespace Settings {
|
|||||||
ShuffleInteriorEntrances.Hide();
|
ShuffleInteriorEntrances.Hide();
|
||||||
ShuffleGrottoEntrances.SetSelectedIndex(OFF);
|
ShuffleGrottoEntrances.SetSelectedIndex(OFF);
|
||||||
ShuffleGrottoEntrances.Hide();
|
ShuffleGrottoEntrances.Hide();
|
||||||
|
ShuffleOwlDrops.SetSelectedIndex(OFF);
|
||||||
|
ShuffleOwlDrops.Hide();
|
||||||
|
ShuffleWarpSongs.SetSelectedIndex(OFF);
|
||||||
|
ShuffleWarpSongs.Hide();
|
||||||
|
ShuffleOverworldSpawns.SetSelectedIndex(OFF);
|
||||||
|
ShuffleOverworldSpawns.Hide();
|
||||||
|
MixedEntrancePools.SetSelectedIndex(OFF);
|
||||||
|
MixedEntrancePools.Hide();
|
||||||
|
DecoupleEntrances.SetSelectedIndex(OFF);
|
||||||
|
DecoupleEntrances.Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only show the options for mixing each pool if they're already being shuffled
|
||||||
|
if (MixedEntrancePools) {
|
||||||
|
if (ShuffleDungeonEntrances) {
|
||||||
|
MixDungeons.Unhide();
|
||||||
|
} else {
|
||||||
|
MixDungeons.Hide();
|
||||||
|
MixDungeons.SetSelectedIndex(OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShuffleOverworldEntrances) {
|
||||||
|
MixOverworld.Unhide();
|
||||||
|
} else {
|
||||||
|
MixOverworld.Hide();
|
||||||
|
MixOverworld.SetSelectedIndex(OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShuffleInteriorEntrances.IsNot(OFF)) {
|
||||||
|
MixInteriors.Unhide();
|
||||||
|
} else {
|
||||||
|
MixInteriors.Hide();
|
||||||
|
MixInteriors.SetSelectedIndex(OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShuffleGrottoEntrances) {
|
||||||
|
MixGrottos.Unhide();
|
||||||
|
} else {
|
||||||
|
MixGrottos.Hide();
|
||||||
|
MixGrottos.SetSelectedIndex(OFF);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MixDungeons.Hide();
|
||||||
|
MixDungeons.SetSelectedIndex(OFF);
|
||||||
|
MixOverworld.Hide();
|
||||||
|
MixOverworld.SetSelectedIndex(OFF);
|
||||||
|
MixInteriors.Hide();
|
||||||
|
MixInteriors.SetSelectedIndex(OFF);
|
||||||
|
MixGrottos.Hide();
|
||||||
|
MixGrottos.SetSelectedIndex(OFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2365,6 +2447,18 @@ namespace Settings {
|
|||||||
ShuffleOverworldEntrances.SetSelectedIndex(OFF);
|
ShuffleOverworldEntrances.SetSelectedIndex(OFF);
|
||||||
ShuffleInteriorEntrances.SetSelectedIndex(OFF);
|
ShuffleInteriorEntrances.SetSelectedIndex(OFF);
|
||||||
ShuffleGrottoEntrances.SetSelectedIndex(OFF);
|
ShuffleGrottoEntrances.SetSelectedIndex(OFF);
|
||||||
|
ShuffleOwlDrops.SetSelectedIndex(OFF);
|
||||||
|
ShuffleWarpSongs.SetSelectedIndex(OFF);
|
||||||
|
ShuffleOverworldSpawns.SetSelectedIndex(OFF);
|
||||||
|
MixedEntrancePools.SetSelectedIndex(OFF);
|
||||||
|
DecoupleEntrances.SetSelectedIndex(OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MixedEntrancePools) {
|
||||||
|
MixDungeons.SetSelectedIndex(OFF);
|
||||||
|
MixOverworld.SetSelectedIndex(OFF);
|
||||||
|
MixInteriors.SetSelectedIndex(OFF);
|
||||||
|
MixGrottos.SetSelectedIndex(OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shuffle Settings
|
// Shuffle Settings
|
||||||
@ -2569,6 +2663,15 @@ namespace Settings {
|
|||||||
ShuffleOverworldEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES]);
|
ShuffleOverworldEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES]);
|
||||||
ShuffleInteriorEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES]);
|
ShuffleInteriorEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES]);
|
||||||
ShuffleGrottoEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_GROTTO_ENTRANCES]);
|
ShuffleGrottoEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_GROTTO_ENTRANCES]);
|
||||||
|
ShuffleOwlDrops.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OWL_DROPS]);
|
||||||
|
ShuffleWarpSongs.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_WARP_SONGS]);
|
||||||
|
ShuffleOverworldSpawns.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS]);
|
||||||
|
MixedEntrancePools.SetSelectedIndex(cvarSettings[RSK_MIXED_ENTRANCE_POOLS]);
|
||||||
|
MixDungeons.SetSelectedIndex(cvarSettings[RSK_MIX_DUNGEON_ENTRANCES]);
|
||||||
|
MixOverworld.SetSelectedIndex(cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES]);
|
||||||
|
MixInteriors.SetSelectedIndex(cvarSettings[RSK_MIX_INTERIOR_ENTRANCES]);
|
||||||
|
MixGrottos.SetSelectedIndex(cvarSettings[RSK_MIX_GROTTO_ENTRANCES]);
|
||||||
|
DecoupleEntrances.SetSelectedIndex(cvarSettings[RSK_DECOUPLED_ENTRANCES]);
|
||||||
|
|
||||||
// if we skip child zelda, we start with zelda's letter, and malon starts
|
// if we skip child zelda, we start with zelda's letter, and malon starts
|
||||||
// at the ranch, so we should *not* shuffle the weird egg
|
// at the ranch, so we should *not* shuffle the weird egg
|
||||||
|
@ -390,6 +390,15 @@ typedef struct {
|
|||||||
uint8_t shuffleOverworldEntrances;
|
uint8_t shuffleOverworldEntrances;
|
||||||
uint8_t shuffleInteriorEntrances;
|
uint8_t shuffleInteriorEntrances;
|
||||||
uint8_t shuffleGrottoEntrances;
|
uint8_t shuffleGrottoEntrances;
|
||||||
|
uint8_t shuffleOwlDrops;
|
||||||
|
uint8_t shuffleWarpSongs;
|
||||||
|
uint8_t shuffleOverworldSpawns;
|
||||||
|
uint8_t mixedEntrancePools;
|
||||||
|
uint8_t mixDungeons;
|
||||||
|
uint8_t mixOverworld;
|
||||||
|
uint8_t mixInteriors;
|
||||||
|
uint8_t mixGrottos;
|
||||||
|
uint8_t decoupleEntrances;
|
||||||
uint8_t bombchusInLogic;
|
uint8_t bombchusInLogic;
|
||||||
uint8_t ammoDrops;
|
uint8_t ammoDrops;
|
||||||
uint8_t heartDropRefill;
|
uint8_t heartDropRefill;
|
||||||
@ -897,6 +906,15 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
|
|||||||
extern Option ShuffleOverworldEntrances;
|
extern Option ShuffleOverworldEntrances;
|
||||||
extern Option ShuffleInteriorEntrances;
|
extern Option ShuffleInteriorEntrances;
|
||||||
extern Option ShuffleGrottoEntrances;
|
extern Option ShuffleGrottoEntrances;
|
||||||
|
extern Option ShuffleOwlDrops;
|
||||||
|
extern Option ShuffleWarpSongs;
|
||||||
|
extern Option ShuffleOverworldSpawns;
|
||||||
|
extern Option MixedEntrancePools;
|
||||||
|
extern Option MixDungeons;
|
||||||
|
extern Option MixOverworld;
|
||||||
|
extern Option MixInteriors;
|
||||||
|
extern Option MixGrottos;
|
||||||
|
extern Option DecoupleEntrances;
|
||||||
extern Option BombchusInLogic;
|
extern Option BombchusInLogic;
|
||||||
extern Option AmmoDrops;
|
extern Option AmmoDrops;
|
||||||
extern Option HeartDropRefill;
|
extern Option HeartDropRefill;
|
||||||
|
@ -298,18 +298,20 @@ static void WriteLocation(
|
|||||||
//Writes a shuffled entrance to the specified node
|
//Writes a shuffled entrance to the specified node
|
||||||
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 = entrance->GetReverse()->GetIndex();
|
int16_t destinationIndex = -1;
|
||||||
int16_t originalBlueWarp = entrance->GetBlueWarp();
|
int16_t originalBlueWarp = entrance->GetBlueWarp();
|
||||||
int16_t replacementBlueWarp = entrance->GetReplacement()->GetReverse()->GetBlueWarp();
|
int16_t replacementBlueWarp = -1;
|
||||||
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
||||||
int16_t replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
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;
|
||||||
|
|
||||||
switch (gSaveContext.language) {
|
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||||
case LANGUAGE_ENG:
|
destinationIndex = entrance->GetReverse()->GetIndex();
|
||||||
case LANGUAGE_FRA:
|
replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
||||||
default:
|
replacementBlueWarp = entrance->GetReplacement()->GetReverse()->GetBlueWarp();
|
||||||
|
}
|
||||||
|
|
||||||
json entranceJson = json::object({
|
json entranceJson = json::object({
|
||||||
{"index", originalIndex},
|
{"index", originalIndex},
|
||||||
{"destination", destinationIndex},
|
{"destination", destinationIndex},
|
||||||
@ -321,7 +323,7 @@ static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance)
|
|||||||
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 with blue warps
|
||||||
if (!false) { // RANDOTODO: add check for decoupled entrances
|
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||||
json reverseEntranceJson = json::object({
|
json reverseEntranceJson = json::object({
|
||||||
{"index", replacementDestinationIndex},
|
{"index", replacementDestinationIndex},
|
||||||
{"destination", replacementIndex},
|
{"destination", replacementIndex},
|
||||||
@ -333,6 +335,10 @@ static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance)
|
|||||||
jsonData["entrances"].push_back(reverseEntranceJson);
|
jsonData["entrances"].push_back(reverseEntranceJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (gSaveContext.language) {
|
||||||
|
case LANGUAGE_ENG:
|
||||||
|
case LANGUAGE_FRA:
|
||||||
|
default:
|
||||||
jsonData["entrancesMap"][sphereString][name] = text;
|
jsonData["entrancesMap"][sphereString][name] = text;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -628,12 +634,24 @@ static void WriteHints(int language) {
|
|||||||
default:
|
default:
|
||||||
unformattedGanonText = GetGanonText().GetEnglish();
|
unformattedGanonText = GetGanonText().GetEnglish();
|
||||||
unformattedGanonHintText = GetGanonHintText().GetEnglish();
|
unformattedGanonHintText = GetGanonHintText().GetEnglish();
|
||||||
|
jsonData["warpMinuetText"] = GetWarpMinuetText().GetEnglish();
|
||||||
|
jsonData["warpBoleroText"] = GetWarpBoleroText().GetEnglish();
|
||||||
|
jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetEnglish();
|
||||||
|
jsonData["warpRequiemText"] = GetWarpRequiemText().GetEnglish();
|
||||||
|
jsonData["warpNocturne"] = GetWarpNocturneText().GetEnglish();
|
||||||
|
jsonData["warpPreludeText"] = GetWarpPreludeText().GetEnglish();
|
||||||
jsonData["childAltarText"] = GetChildAltarText().GetEnglish();
|
jsonData["childAltarText"] = GetChildAltarText().GetEnglish();
|
||||||
jsonData["adultAltarText"] = GetAdultAltarText().GetEnglish();
|
jsonData["adultAltarText"] = GetAdultAltarText().GetEnglish();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
unformattedGanonText = GetGanonText().GetFrench();
|
unformattedGanonText = GetGanonText().GetFrench();
|
||||||
unformattedGanonHintText = GetGanonHintText().GetFrench();
|
unformattedGanonHintText = GetGanonHintText().GetFrench();
|
||||||
|
jsonData["warpMinuetText"] = GetWarpMinuetText().GetFrench();
|
||||||
|
jsonData["warpBoleroText"] = GetWarpBoleroText().GetFrench();
|
||||||
|
jsonData["warpSerenadeText"] = GetWarpSerenadeText().GetFrench();
|
||||||
|
jsonData["warpRequiemText"] = GetWarpRequiemText().GetFrench();
|
||||||
|
jsonData["warpNocturne"] = GetWarpNocturneText().GetFrench();
|
||||||
|
jsonData["warpPreludeText"] = GetWarpPreludeText().GetFrench();
|
||||||
jsonData["childAltarText"] = GetChildAltarText().GetFrench();
|
jsonData["childAltarText"] = GetChildAltarText().GetFrench();
|
||||||
jsonData["adultAltarText"] = GetAdultAltarText().GetFrench();
|
jsonData["adultAltarText"] = GetAdultAltarText().GetFrench();
|
||||||
break;
|
break;
|
||||||
|
@ -224,6 +224,15 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
|
|||||||
{ "World Settings:Overworld Entrances", RSK_SHUFFLE_OVERWORLD_ENTRANCES },
|
{ "World Settings:Overworld Entrances", RSK_SHUFFLE_OVERWORLD_ENTRANCES },
|
||||||
{ "World Settings:Interior Entrances", RSK_SHUFFLE_INTERIOR_ENTRANCES },
|
{ "World Settings:Interior Entrances", RSK_SHUFFLE_INTERIOR_ENTRANCES },
|
||||||
{ "World Settings:Grottos Entrances", RSK_SHUFFLE_GROTTO_ENTRANCES },
|
{ "World Settings:Grottos Entrances", RSK_SHUFFLE_GROTTO_ENTRANCES },
|
||||||
|
{ "World Settings:Owl Drops", RSK_SHUFFLE_OWL_DROPS },
|
||||||
|
{ "World Settings:Warp Songs", RSK_SHUFFLE_WARP_SONGS },
|
||||||
|
{ "World Settings:Overworld Spawns", RSK_SHUFFLE_OVERWORLD_SPAWNS },
|
||||||
|
{ "World Settings:Mixed Entrance Pools", RSK_MIXED_ENTRANCE_POOLS },
|
||||||
|
{ "World Settings:Mix Dungeons", RSK_MIX_DUNGEON_ENTRANCES },
|
||||||
|
{ "World Settings:Mix Overworld", RSK_MIX_OVERWORLD_ENTRANCES },
|
||||||
|
{ "World Settings:Mix Interiors", RSK_MIX_INTERIOR_ENTRANCES },
|
||||||
|
{ "World Settings:Mix Grottos", RSK_MIX_GROTTO_ENTRANCES },
|
||||||
|
{ "World Settings:Decouple Entrances", RSK_DECOUPLED_ENTRANCES },
|
||||||
{ "Misc Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS },
|
{ "Misc Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS },
|
||||||
{ "Misc Settings:Hint Clarity", RSK_HINT_CLARITY },
|
{ "Misc Settings:Hint Clarity", RSK_HINT_CLARITY },
|
||||||
{ "Misc Settings:Hint Distribution", RSK_HINT_DISTRIBUTION },
|
{ "Misc Settings:Hint Distribution", RSK_HINT_DISTRIBUTION },
|
||||||
@ -327,6 +336,12 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
|
|||||||
CustomMessageManager::Instance->CreateMessage(
|
CustomMessageManager::Instance->CreateMessage(
|
||||||
Randomizer::hintMessageTableID, hintLocation.check, { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, hintLocation.hintText, hintLocation.hintText, hintLocation.hintText });
|
Randomizer::hintMessageTableID, hintLocation.check, { TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, hintLocation.hintText, hintLocation.hintText, hintLocation.hintText });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_WARP_RANDOM_REPLACED_TEXT,
|
||||||
|
{ TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM,
|
||||||
|
"Warp to&{{location}}?\x1B&%gOK&No%w\x02",
|
||||||
|
"Warp to&{{location}}?\x1B&%gOK&No%w\x02", // TODO: German translation
|
||||||
|
"Se téléporter vers&{{location}}?\x1B&%gOK!&Non%w\x02" });
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RandomizerCheck> shopItemRandomizerChecks = {
|
std::vector<RandomizerCheck> shopItemRandomizerChecks = {
|
||||||
@ -716,6 +731,15 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
|||||||
case RSK_SHUFFLE_ENTRANCES:
|
case RSK_SHUFFLE_ENTRANCES:
|
||||||
case RSK_SHUFFLE_OVERWORLD_ENTRANCES:
|
case RSK_SHUFFLE_OVERWORLD_ENTRANCES:
|
||||||
case RSK_SHUFFLE_GROTTO_ENTRANCES:
|
case RSK_SHUFFLE_GROTTO_ENTRANCES:
|
||||||
|
case RSK_SHUFFLE_OWL_DROPS:
|
||||||
|
case RSK_SHUFFLE_WARP_SONGS:
|
||||||
|
case RSK_SHUFFLE_OVERWORLD_SPAWNS:
|
||||||
|
case RSK_MIXED_ENTRANCE_POOLS:
|
||||||
|
case RSK_MIX_DUNGEON_ENTRANCES:
|
||||||
|
case RSK_MIX_OVERWORLD_ENTRANCES:
|
||||||
|
case RSK_MIX_INTERIOR_ENTRANCES:
|
||||||
|
case RSK_MIX_GROTTO_ENTRANCES:
|
||||||
|
case RSK_DECOUPLED_ENTRANCES:
|
||||||
if(it.value() == "Off") {
|
if(it.value() == "Off") {
|
||||||
gSaveContext.randoSettings[index].value = RO_GENERIC_OFF;
|
gSaveContext.randoSettings[index].value = RO_GENERIC_OFF;
|
||||||
} else if(it.value() == "On") {
|
} else if(it.value() == "On") {
|
||||||
@ -1101,6 +1125,30 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) {
|
|||||||
strncpy(gSaveContext.ganonText, formattedGanonJsonText.c_str(), sizeof(gSaveContext.ganonText) - 1);
|
strncpy(gSaveContext.ganonText, formattedGanonJsonText.c_str(), sizeof(gSaveContext.ganonText) - 1);
|
||||||
gSaveContext.ganonText[sizeof(gSaveContext.ganonText) - 1] = 0;
|
gSaveContext.ganonText[sizeof(gSaveContext.ganonText) - 1] = 0;
|
||||||
|
|
||||||
|
std::string warpMinuetJsonText = spoilerFileJson["warpMinuetText"].get<std::string>();
|
||||||
|
strncpy(gSaveContext.warpMinuetText, warpMinuetJsonText.c_str(), sizeof(gSaveContext.warpMinuetText) - 1);
|
||||||
|
gSaveContext.warpMinuetText[sizeof(gSaveContext.warpMinuetText) - 1] = 0;
|
||||||
|
|
||||||
|
std::string warpBoleroJsonText = spoilerFileJson["warpBoleroText"].get<std::string>();
|
||||||
|
strncpy(gSaveContext.warpBoleroText, warpBoleroJsonText.c_str(), sizeof(gSaveContext.warpBoleroText) - 1);
|
||||||
|
gSaveContext.warpBoleroText[sizeof(gSaveContext.warpBoleroText) - 1] = 0;
|
||||||
|
|
||||||
|
std::string warpSerenadeJsonText = spoilerFileJson["warpSerenadeText"].get<std::string>();
|
||||||
|
strncpy(gSaveContext.warpSerenadeText, warpSerenadeJsonText.c_str(), sizeof(gSaveContext.warpSerenadeText) - 1);
|
||||||
|
gSaveContext.warpSerenadeText[sizeof(gSaveContext.warpSerenadeText) - 1] = 0;
|
||||||
|
|
||||||
|
std::string warpRequiemJsonText = spoilerFileJson["warpRequiemText"].get<std::string>();
|
||||||
|
strncpy(gSaveContext.warpRequiemText, warpRequiemJsonText.c_str(), sizeof(gSaveContext.warpRequiemText) - 1);
|
||||||
|
gSaveContext.warpRequiemText[sizeof(gSaveContext.warpRequiemText) - 1] = 0;
|
||||||
|
|
||||||
|
std::string warpNocturneJsonText = spoilerFileJson["warpNocturneText"].get<std::string>();
|
||||||
|
strncpy(gSaveContext.warpNocturneText, warpNocturneJsonText.c_str(), sizeof(gSaveContext.warpNocturneText) - 1);
|
||||||
|
gSaveContext.warpNocturneText[sizeof(gSaveContext.warpNocturneText) - 1] = 0;
|
||||||
|
|
||||||
|
std::string warpPreludeJsonText = spoilerFileJson["warpPreludeText"].get<std::string>();
|
||||||
|
strncpy(gSaveContext.warpPreludeText, warpPreludeJsonText.c_str(), sizeof(gSaveContext.warpPreludeText) - 1);
|
||||||
|
gSaveContext.warpPreludeText[sizeof(gSaveContext.warpPreludeText) - 1] = 0;
|
||||||
|
|
||||||
json hintsJson = spoilerFileJson["hints"];
|
json hintsJson = spoilerFileJson["hints"];
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (auto it = hintsJson.begin(); it != hintsJson.end(); ++it) {
|
for (auto it = hintsJson.begin(); it != hintsJson.end(); ++it) {
|
||||||
@ -2682,15 +2730,27 @@ void GenerateRandomizerImgui() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enable if any of the entrance rando options are enabled.
|
// Enable if any of the entrance rando options are enabled.
|
||||||
cvarSettings[RSK_SHUFFLE_ENTRANCES] = CVar_GetS32("gRandomizeShuffleDungeonsEntrances", 0) ||
|
cvarSettings[RSK_SHUFFLE_ENTRANCES] = CVar_GetS32("gRandomizeShuffleDungeonsEntrances", RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) ||
|
||||||
CVar_GetS32("gRandomizeShuffleOverworldEntrances", 0) ||
|
CVar_GetS32("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF) ||
|
||||||
CVar_GetS32("gRandomizeShuffleInteriorsEntrances", 0) ||
|
CVar_GetS32("gRandomizeShuffleInteriorsEntrances", RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) ||
|
||||||
CVar_GetS32("gRandomizeShuffleGrottosEntrances", 0);
|
CVar_GetS32("gRandomizeShuffleGrottosEntrances", RO_GENERIC_OFF) ||
|
||||||
|
CVar_GetS32("gRandomizeShuffleOwlDrops", RO_GENERIC_OFF) ||
|
||||||
|
CVar_GetS32("gRandomizeShuffleWarpSongs", RO_GENERIC_OFF) ||
|
||||||
|
CVar_GetS32("gRandomizeShuffleOverworldSpawns", RO_GENERIC_OFF);
|
||||||
|
|
||||||
cvarSettings[RSK_SHUFFLE_DUNGEON_ENTRANCES] = CVar_GetS32("gRandomizeShuffleDungeonsEntrances", 0);
|
cvarSettings[RSK_SHUFFLE_DUNGEON_ENTRANCES] = CVar_GetS32("gRandomizeShuffleDungeonsEntrances", RO_DUNGEON_ENTRANCE_SHUFFLE_OFF);
|
||||||
cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES] = CVar_GetS32("gRandomizeShuffleOverworldEntrances", 0);
|
cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES] = CVar_GetS32("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF);
|
||||||
cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES] = CVar_GetS32("gRandomizeShuffleInteriorsEntrances", 0);
|
cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES] = CVar_GetS32("gRandomizeShuffleInteriorsEntrances", RO_INTERIOR_ENTRANCE_SHUFFLE_OFF);
|
||||||
cvarSettings[RSK_SHUFFLE_GROTTO_ENTRANCES] = CVar_GetS32("gRandomizeShuffleGrottosEntrances", 0);
|
cvarSettings[RSK_SHUFFLE_GROTTO_ENTRANCES] = CVar_GetS32("gRandomizeShuffleGrottosEntrances", RO_GENERIC_OFF);
|
||||||
|
cvarSettings[RSK_SHUFFLE_OWL_DROPS] = CVar_GetS32("gRandomizeShuffleOwlDrops", RO_GENERIC_OFF);
|
||||||
|
cvarSettings[RSK_SHUFFLE_WARP_SONGS] = CVar_GetS32("gRandomizeShuffleWarpSongs", RO_GENERIC_OFF);
|
||||||
|
cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS] = CVar_GetS32("gRandomizeShuffleOverworldSpawns", RO_GENERIC_OFF);
|
||||||
|
cvarSettings[RSK_MIXED_ENTRANCE_POOLS] = CVar_GetS32("gRandomizeMixedEntrances", RO_GENERIC_OFF);
|
||||||
|
cvarSettings[RSK_MIX_DUNGEON_ENTRANCES] = CVar_GetS32("gRandomizeMixDungeons", RO_GENERIC_OFF);
|
||||||
|
cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES] = CVar_GetS32("gRandomizeMixOverworld", RO_GENERIC_OFF);
|
||||||
|
cvarSettings[RSK_MIX_INTERIOR_ENTRANCES] = CVar_GetS32("gRandomizeMixInteriors", RO_GENERIC_OFF);
|
||||||
|
cvarSettings[RSK_MIX_GROTTO_ENTRANCES] = CVar_GetS32("gRandomizeMixGrottos", RO_GENERIC_OFF);
|
||||||
|
cvarSettings[RSK_DECOUPLED_ENTRANCES] = CVar_GetS32("gRandomizeShuffleDecoupledEntrances", RO_GENERIC_OFF);
|
||||||
|
|
||||||
// todo: this efficently when we build out cvar array support
|
// todo: this efficently when we build out cvar array support
|
||||||
std::set<RandomizerCheck> excludedLocations;
|
std::set<RandomizerCheck> excludedLocations;
|
||||||
@ -3108,6 +3168,88 @@ void DrawRandoEditor(bool& open) {
|
|||||||
"Shuffle the pool of grotto entrances, including all graves, small Fairy fountains and the Deku Theatre."
|
"Shuffle the pool of grotto entrances, including all graves, small Fairy fountains and the Deku Theatre."
|
||||||
);
|
);
|
||||||
|
|
||||||
|
UIWidgets::PaddedSeparator();
|
||||||
|
|
||||||
|
// Shuffle Owl Drops
|
||||||
|
UIWidgets::EnhancementCheckbox("Shuffle Owl Drops", "gRandomizeShuffleOwlDrops");
|
||||||
|
UIWidgets::InsertHelpHoverText(
|
||||||
|
"Randomize where Kaepora Gaebora (the Owl) drops you at when you talk "
|
||||||
|
"to him at Lake Hylia or at the top of Death Mountain Trail."
|
||||||
|
);
|
||||||
|
|
||||||
|
UIWidgets::PaddedSeparator();
|
||||||
|
|
||||||
|
// Shuffle Warp Songs
|
||||||
|
UIWidgets::EnhancementCheckbox("Shuffle Warp Songs", "gRandomizeShuffleWarpSongs");
|
||||||
|
UIWidgets::InsertHelpHoverText(
|
||||||
|
"Randomize where each of the 6 warp songs leads to."
|
||||||
|
);
|
||||||
|
|
||||||
|
UIWidgets::PaddedSeparator();
|
||||||
|
|
||||||
|
// Shuffle Overworld Spawns
|
||||||
|
UIWidgets::EnhancementCheckbox("Shuffle Overworld Spawns", "gRandomizeShuffleOverworldSpawns");
|
||||||
|
UIWidgets::InsertHelpHoverText(
|
||||||
|
"Randomize where you start as Child or Adult when loading a save in the Overworld. This "
|
||||||
|
"means you may not necessarily spawn inside Link's House or Temple of Time.\n"
|
||||||
|
"\n"
|
||||||
|
"This stays consistent after saving and loading the game again.\n"
|
||||||
|
"\n"
|
||||||
|
"Keep in mind you may need to temporarily disable the \"Remember Save Location\" time saver to "
|
||||||
|
"be able use the spawn positions, especially if they are the only logical way to get to certain areas."
|
||||||
|
);
|
||||||
|
|
||||||
|
UIWidgets::PaddedSeparator();
|
||||||
|
|
||||||
|
// Shuffle Decoupled Entrances
|
||||||
|
UIWidgets::EnhancementCheckbox("Shuffle Decoupled Entrances", "gRandomizeShuffleDecoupledEntrances");
|
||||||
|
UIWidgets::InsertHelpHoverText(
|
||||||
|
"Decouple entrances when shuffling them. This means you are no longer guaranteed "
|
||||||
|
"to end up back where you came from when you go back through an entrance.\n"
|
||||||
|
"\n"
|
||||||
|
"This also adds the one-way entrance from Gerudo Valley to Lake Hylia in the pool of "
|
||||||
|
"overworld entrances when they are shuffled."
|
||||||
|
);
|
||||||
|
|
||||||
|
UIWidgets::PaddedSeparator();
|
||||||
|
|
||||||
|
// Mixed Entrance Pools
|
||||||
|
UIWidgets::EnhancementCheckbox("Mixed Entrance Pools", "gRandomizeMixedEntrances");
|
||||||
|
UIWidgets::InsertHelpHoverText(
|
||||||
|
"Shuffle entrances into a mixed pool instead of separate ones.\n"
|
||||||
|
"\n"
|
||||||
|
"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 "
|
||||||
|
"vice versa, while overworld entrances are shuffled in their own separate pool and indoors stay vanilla."
|
||||||
|
);
|
||||||
|
|
||||||
|
if (CVar_GetS32("gRandomizeMixedEntrances", RO_GENERIC_OFF)) {
|
||||||
|
if (CVar_GetS32("gRandomizeShuffleDungeonsEntrances", RO_GENERIC_OFF)) {
|
||||||
|
UIWidgets::Spacer(0);
|
||||||
|
ImGui::SetCursorPosX(20);
|
||||||
|
UIWidgets::EnhancementCheckbox("Mix Dungeons", "gRandomizeMixDungeons");
|
||||||
|
UIWidgets::InsertHelpHoverText("Dungeon entrances will be part of the mixed pool");
|
||||||
|
}
|
||||||
|
if (CVar_GetS32("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF)) {
|
||||||
|
UIWidgets::Spacer(0);
|
||||||
|
ImGui::SetCursorPosX(20);
|
||||||
|
UIWidgets::EnhancementCheckbox("Mix Overworld", "gRandomizeMixOverworld");
|
||||||
|
UIWidgets::InsertHelpHoverText("Overworld entrances will be part of the mixed pool");
|
||||||
|
}
|
||||||
|
if (CVar_GetS32("gRandomizeShuffleInteriorsEntrances", RO_GENERIC_OFF)) {
|
||||||
|
UIWidgets::Spacer(0);
|
||||||
|
ImGui::SetCursorPosX(20);
|
||||||
|
UIWidgets::EnhancementCheckbox("Mix Interiors", "gRandomizeMixInteriors");
|
||||||
|
UIWidgets::InsertHelpHoverText("Interior entrances will be part of the mixed pool");
|
||||||
|
}
|
||||||
|
if (CVar_GetS32("gRandomizeShuffleGrottosEntrances", RO_GENERIC_OFF)) {
|
||||||
|
UIWidgets::Spacer(0);
|
||||||
|
ImGui::SetCursorPosX(20);
|
||||||
|
UIWidgets::EnhancementCheckbox("Mix Grotts", "gRandomizeMixGrottos");
|
||||||
|
UIWidgets::InsertHelpHoverText("Grotto entrances will be part of the mixed pool");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
@ -4016,6 +4158,47 @@ void DrawRandoEditor(bool& open) {
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CustomMessageEntry Randomizer::GetWarpSongMessage(u16 textId, bool mysterious) {
|
||||||
|
CustomMessageEntry messageEntry = CustomMessageManager::Instance->RetrieveMessage(
|
||||||
|
Randomizer::hintMessageTableID, TEXT_WARP_RANDOM_REPLACED_TEXT);
|
||||||
|
if (mysterious) {
|
||||||
|
std::vector<std::string> locationName ={
|
||||||
|
"a mysterious place",
|
||||||
|
"a mysterious place", // TODO: German translation
|
||||||
|
"un endroit mystérieux",
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomMessageManager::ReplaceStringInMessage(messageEntry, "{{location}}", locationName[0],
|
||||||
|
locationName[1], locationName[2]);
|
||||||
|
return messageEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string locationName;
|
||||||
|
switch (textId) {
|
||||||
|
case TEXT_WARP_MINUET_OF_FOREST:
|
||||||
|
locationName = std::string(gSaveContext.warpMinuetText);
|
||||||
|
break;
|
||||||
|
case TEXT_WARP_BOLERO_OF_FIRE:
|
||||||
|
locationName = std::string(gSaveContext.warpBoleroText);
|
||||||
|
break;
|
||||||
|
case TEXT_WARP_SERENADE_OF_WATER:
|
||||||
|
locationName = std::string(gSaveContext.warpSerenadeText);
|
||||||
|
break;
|
||||||
|
case TEXT_WARP_REQUIEM_OF_SPIRIT:
|
||||||
|
locationName = std::string(gSaveContext.warpRequiemText);
|
||||||
|
break;
|
||||||
|
case TEXT_WARP_NOCTURNE_OF_SHADOW:
|
||||||
|
locationName = std::string(gSaveContext.warpNocturneText);
|
||||||
|
break;
|
||||||
|
case TEXT_WARP_PRELUDE_OF_LIGHT:
|
||||||
|
locationName = std::string(gSaveContext.warpPreludeText);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomMessageManager::ReplaceStringInMessage(messageEntry, "{{location}}", locationName);
|
||||||
|
return messageEntry;
|
||||||
|
}
|
||||||
|
|
||||||
CustomMessageEntry Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious) {
|
CustomMessageEntry Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious) {
|
||||||
CustomMessageEntry messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId);
|
CustomMessageEntry messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId);
|
||||||
RandomizerCheck rc = GetCheckFromRandomizerInf(randomizerInf);
|
RandomizerCheck rc = GetCheckFromRandomizerInf(randomizerInf);
|
||||||
|
@ -77,6 +77,7 @@ class Randomizer {
|
|||||||
GetItemID GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId);
|
GetItemID GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId);
|
||||||
ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck);
|
ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck);
|
||||||
ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck);
|
ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck);
|
||||||
|
CustomMessageEntry GetWarpSongMessage(u16 textId, bool mysterious = false);
|
||||||
CustomMessageEntry GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious = false);
|
CustomMessageEntry GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious = false);
|
||||||
CustomMessageEntry GetMapGetItemMessageWithHint(GetItemEntry itemEntry);
|
CustomMessageEntry GetMapGetItemMessageWithHint(GetItemEntry itemEntry);
|
||||||
static void CreateCustomMessages();
|
static void CreateCustomMessages();
|
||||||
|
@ -59,6 +59,14 @@ static void Entrance_SeparateOGCFairyFountainExit(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Entrance_SeparateAdultSpawnAndPrelude() {
|
||||||
|
// Overwrite unused entrance 0x0282 with values from 0x05F4 to use it as the
|
||||||
|
// Adult Spawn index and separate it from Prelude of Light
|
||||||
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
|
gEntranceTable[0x282 + i] = gEntranceTable[0x5F4 + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Entrance_CopyOriginalEntranceTable(void) {
|
void Entrance_CopyOriginalEntranceTable(void) {
|
||||||
if (!hasCopiedEntranceTable) {
|
if (!hasCopiedEntranceTable) {
|
||||||
memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * 1556);
|
memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * 1556);
|
||||||
@ -91,6 +99,7 @@ void Entrance_Init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entrance_SeparateOGCFairyFountainExit();
|
Entrance_SeparateOGCFairyFountainExit();
|
||||||
|
Entrance_SeparateAdultSpawnAndPrelude();
|
||||||
|
|
||||||
// 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.
|
||||||
@ -188,7 +197,7 @@ s16 Entrance_OverrideNextIndex(s16 nextEntranceIndex) {
|
|||||||
|
|
||||||
// Exiting through the crawl space from Hyrule Castle courtyard is the same exit as leaving Ganon's castle
|
// Exiting through the crawl space from Hyrule Castle courtyard is the same exit as leaving Ganon's castle
|
||||||
// If we came from the Castle courtyard, then don't override the entrance to keep Link in Hyrule Castle area
|
// If we came from the Castle courtyard, then don't override the entrance to keep Link in Hyrule Castle area
|
||||||
if (gPlayState->sceneNum == 69 && nextEntranceIndex == 0x023D) {
|
if (gPlayState != NULL && gPlayState->sceneNum == 69 && nextEntranceIndex == 0x023D) {
|
||||||
return nextEntranceIndex;
|
return nextEntranceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,15 +288,58 @@ void Entrance_SetSavewarpEntrance(void) {
|
|||||||
} else if (scene == SCENE_GERUDOWAY) { // Theives hideout
|
} else if (scene == SCENE_GERUDOWAY) { // Theives hideout
|
||||||
gSaveContext.entranceIndex = 0x0486; // Gerudo Fortress -> Thieve's Hideout spawn 0
|
gSaveContext.entranceIndex = 0x0486; // Gerudo Fortress -> Thieve's Hideout spawn 0
|
||||||
} else if (scene == SCENE_LINK_HOME) {
|
} else if (scene == SCENE_LINK_HOME) {
|
||||||
gSaveContext.entranceIndex = LINK_HOUSE_SAVEWARP_ENTRANCE;
|
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE);
|
||||||
} else if (LINK_IS_CHILD) {
|
} else if (LINK_IS_CHILD) {
|
||||||
gSaveContext.entranceIndex = Entrance_GetOverride(LINK_HOUSE_SAVEWARP_ENTRANCE);
|
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); // Child Overworld Spawn
|
||||||
} else {
|
} else {
|
||||||
gSaveContext.entranceIndex = Entrance_GetOverride(0x05F4); // Temple of Time Adult Spawn
|
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(0x0282); // Adult Overworld Spawn (Normally 0x5F4, but 0x282 has been repurposed to differentiate from Prelude which also uses 0x5F4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entrance_SetWarpSongEntrance(void) {
|
||||||
|
gPlayState->sceneLoadFlag = 0x14;
|
||||||
|
gPlayState->fadeTransition = 5;
|
||||||
|
switch (gPlayState->msgCtx.lastPlayedSong) {
|
||||||
|
case 0:
|
||||||
|
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x0600); // Minuet
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x04F6); // Bolero
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x0604); // Serenade
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x01F1); // Requiem
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x0568); // Nocturne
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x05F4); // Prelude
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gPlayState->sceneLoadFlag = 0; // if something goes wrong, the animation plays normally
|
||||||
|
}
|
||||||
|
|
||||||
|
// If one of the warp songs happens to lead to a grotto return, then we
|
||||||
|
// have to force the grotto return afterwards
|
||||||
|
Grotto_ForceGrottoReturnOnSpecialEntrance();
|
||||||
|
|
||||||
|
if (gSaveContext.gameMode != 0) {
|
||||||
|
// During DHWW the cutscene must play at the destination
|
||||||
|
gSaveContext.respawnFlag = -3;
|
||||||
|
} else if (gSaveContext.respawnFlag == -3) {
|
||||||
|
// Unset Zoneout Type -3 to avoid cutscene at destination (technically it's not needed)
|
||||||
|
gSaveContext.respawnFlag = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entrance_OverrideBlueWarp(void) {
|
void Entrance_OverrideBlueWarp(void) {
|
||||||
|
// Set nextEntranceIndex as a flag so that Grotto_CheckSpecialEntrance
|
||||||
|
// won't return index 0x7FFF, which can't work to override blue warps.
|
||||||
|
gPlayState->nextEntranceIndex = 0;
|
||||||
|
|
||||||
switch (gPlayState->sceneNum) {
|
switch (gPlayState->sceneNum) {
|
||||||
case SCENE_YDAN_BOSS: // Ghoma boss room
|
case SCENE_YDAN_BOSS: // Ghoma boss room
|
||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x0457);
|
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x0457);
|
||||||
@ -322,6 +374,8 @@ void Entrance_OverrideCutsceneEntrance(u16 cutsceneCmd) {
|
|||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(newJabuJabusBellyEntrance);
|
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(newJabuJabusBellyEntrance);
|
||||||
gPlayState->sceneLoadFlag = 0x14;
|
gPlayState->sceneLoadFlag = 0x14;
|
||||||
gPlayState->fadeTransition = 2;
|
gPlayState->fadeTransition = 2;
|
||||||
|
// In case Jabu's mouth leads to a grotto return
|
||||||
|
Grotto_ForceGrottoReturnOnSpecialEntrance();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,7 +560,7 @@ void Entrance_OverrideGeurdoGuardCapture(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Entrance_OverrideSpawnScene(s32 sceneNum, s32 spawn) {
|
void Entrance_OverrideSpawnScene(s32 sceneNum, s32 spawn) {
|
||||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) == 2) { // Shuffle Ganon's Castle
|
if (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) == RO_DUNGEON_ENTRANCE_SHUFFLE_ON_PLUS_GANON) {
|
||||||
// Move Hyrule's Castle Courtyard exit spawn to be before the crates so players don't skip Talon
|
// Move Hyrule's Castle Courtyard exit spawn to be before the crates so players don't skip Talon
|
||||||
if (sceneNum == 95 && spawn == 1) {
|
if (sceneNum == 95 && spawn == 1) {
|
||||||
gPlayState->linkActorEntry->pos.x = 0x033A;
|
gPlayState->linkActorEntry->pos.x = 0x033A;
|
||||||
|
@ -40,6 +40,7 @@ int16_t Entrance_OverrideNextIndex(int16_t nextEntranceIndex);
|
|||||||
int16_t Entrance_OverrideDynamicExit(int16_t dynamicExitIndex);
|
int16_t Entrance_OverrideDynamicExit(int16_t dynamicExitIndex);
|
||||||
uint32_t Entrance_SceneAndSpawnAre(uint8_t scene, uint8_t spawn);
|
uint32_t Entrance_SceneAndSpawnAre(uint8_t scene, uint8_t spawn);
|
||||||
void Entrance_SetSavewarpEntrance(void);
|
void Entrance_SetSavewarpEntrance(void);
|
||||||
|
void Entrance_SetWarpSongEntrance(void);
|
||||||
void Entrance_OverrideBlueWarp(void);
|
void Entrance_OverrideBlueWarp(void);
|
||||||
void Entrance_OverrideCutsceneEntrance(uint16_t cutsceneCmd);
|
void Entrance_OverrideCutsceneEntrance(uint16_t cutsceneCmd);
|
||||||
void Entrance_HandleEponaState(void);
|
void Entrance_HandleEponaState(void);
|
||||||
|
@ -87,6 +87,7 @@ static s16 grottoExitList[NUM_GROTTOS] = {0};
|
|||||||
static s16 grottoLoadList[NUM_GROTTOS] = {0};
|
static s16 grottoLoadList[NUM_GROTTOS] = {0};
|
||||||
static s8 grottoId = 0xFF;
|
static s8 grottoId = 0xFF;
|
||||||
static s8 lastEntranceType = NOT_GROTTO;
|
static s8 lastEntranceType = NOT_GROTTO;
|
||||||
|
static u8 overridingNextEntrance = false;
|
||||||
|
|
||||||
// Initialize both lists so that each index refers to itself. An index referring
|
// Initialize both lists so that each index refers to itself. An index referring
|
||||||
// to itself means that the entrance is not shuffled. Indices will be overwritten
|
// to itself means that the entrance is not shuffled. Indices will be overwritten
|
||||||
@ -114,15 +115,11 @@ static void Grotto_SetupReturnInfo(GrottoReturnInfo grotto, RespawnMode respawnM
|
|||||||
// Set necessary grotto return data to the Entrance Point, so that voiding out and setting FW work correctly
|
// Set necessary grotto return data to the Entrance Point, so that voiding out and setting FW work correctly
|
||||||
gSaveContext.respawn[respawnMode].entranceIndex = grotto.entranceIndex;
|
gSaveContext.respawn[respawnMode].entranceIndex = grotto.entranceIndex;
|
||||||
gSaveContext.respawn[respawnMode].roomIndex = grotto.room;
|
gSaveContext.respawn[respawnMode].roomIndex = grotto.room;
|
||||||
|
|
||||||
if (false /*mixGrottos == ON*/ || false /*decoupledEntrances == ON*/) {
|
|
||||||
gSaveContext.respawn[respawnMode].playerParams = 0x04FF; // exiting grotto with no initial camera focus
|
gSaveContext.respawn[respawnMode].playerParams = 0x04FF; // exiting grotto with no initial camera focus
|
||||||
}
|
|
||||||
|
|
||||||
gSaveContext.respawn[respawnMode].yaw = grotto.angle;
|
gSaveContext.respawn[respawnMode].yaw = grotto.angle;
|
||||||
gSaveContext.respawn[respawnMode].pos = grotto.pos;
|
gSaveContext.respawn[respawnMode].pos = grotto.pos;
|
||||||
//TODO If Mixed Entrance Pools or decoupled entrances are active, set these flags to 0 instead of restoring them
|
// If Mixed Entrance Pools or decoupled entrances are active, set these flags to 0 instead of restoring them
|
||||||
if (false /*mixGrottos == ON*/ || false /*decoupledEntrances == ON*/) {
|
if (Randomizer_GetSettingValue(RSK_MIX_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_DECOUPLED_ENTRANCES)) {
|
||||||
gSaveContext.respawn[respawnMode].tempSwchFlags = 0;
|
gSaveContext.respawn[respawnMode].tempSwchFlags = 0;
|
||||||
gSaveContext.respawn[respawnMode].tempCollectFlags = 0;
|
gSaveContext.respawn[respawnMode].tempCollectFlags = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -136,7 +133,7 @@ static void Grotto_SetupReturnInfo(GrottoReturnInfo grotto, RespawnMode respawnM
|
|||||||
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
||||||
|
|
||||||
// Don't change anything unless grotto shuffle has been enabled
|
// Don't change anything unless grotto shuffle has been enabled
|
||||||
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
|
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) && !Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) && !Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS)) {
|
||||||
return nextEntranceIndex;
|
return nextEntranceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,13 +154,18 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
|||||||
Grotto_SetupReturnInfo(grotto, RESPAWN_MODE_RETURN);
|
Grotto_SetupReturnInfo(grotto, RESPAWN_MODE_RETURN);
|
||||||
Grotto_SetupReturnInfo(grotto, RESPAWN_MODE_DOWN);
|
Grotto_SetupReturnInfo(grotto, RESPAWN_MODE_DOWN);
|
||||||
|
|
||||||
// When the nextEntranceIndex is determined by a dynamic exit, we have
|
// When the nextEntranceIndex is determined by a dynamic exit,
|
||||||
// to set the respawn information and nextEntranceIndex manually
|
// or set by Entrance_OverrideBlueWarp to mark a blue warp entrance,
|
||||||
|
// we have to set the respawn information and nextEntranceIndex manually
|
||||||
if (gPlayState != NULL && gPlayState->nextEntranceIndex != -1) {
|
if (gPlayState != NULL && gPlayState->nextEntranceIndex != -1) {
|
||||||
gSaveContext.respawnFlag = 2;
|
gSaveContext.respawnFlag = 2;
|
||||||
nextEntranceIndex = grotto.entranceIndex;
|
nextEntranceIndex = grotto.entranceIndex;
|
||||||
gPlayState->fadeTransition = 3;
|
gPlayState->fadeTransition = 3;
|
||||||
gSaveContext.nextTransitionType = 3;
|
gSaveContext.nextTransitionType = 3;
|
||||||
|
} else if (gPlayState == NULL) { // Handle spawn position when loading from a save file
|
||||||
|
gSaveContext.respawnFlag = 2;
|
||||||
|
nextEntranceIndex = grotto.entranceIndex;
|
||||||
|
gSaveContext.nextTransitionType = 3;
|
||||||
// Otherwise return 0x7FFF and let the game handle it
|
// Otherwise return 0x7FFF and let the game handle it
|
||||||
} else {
|
} else {
|
||||||
nextEntranceIndex = 0x7FFF;
|
nextEntranceIndex = 0x7FFF;
|
||||||
@ -185,6 +187,7 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
|||||||
lastEntranceType = NOT_GROTTO;
|
lastEntranceType = NOT_GROTTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
overridingNextEntrance = true;
|
||||||
return nextEntranceIndex;
|
return nextEntranceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,8 +195,8 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
|||||||
// thisx - pointer to the grotto actor
|
// thisx - pointer to the grotto actor
|
||||||
void Grotto_OverrideActorEntrance(Actor* thisx) {
|
void Grotto_OverrideActorEntrance(Actor* thisx) {
|
||||||
|
|
||||||
// Vanilla Behavior if grottos aren't shuffled
|
// Vanilla Behavior if there's no possibility of ending up in a grotto randomly
|
||||||
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
|
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) && !Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) && !Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,10 +219,22 @@ void Grotto_OverrideActorEntrance(Actor* thisx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set necessary flags for when warp songs/overworld spawns are shuffled to grotto return points
|
||||||
|
void Grotto_ForceGrottoReturnOnSpecialEntrance(void) {
|
||||||
|
if (lastEntranceType == GROTTO_RETURN && (Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) || Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS))) {
|
||||||
|
gSaveContext.respawnFlag = 2;
|
||||||
|
gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams = 0x4FF;
|
||||||
|
gSaveContext.respawn[RESPAWN_MODE_RETURN].pos = grottoReturnTable[grottoId].pos;
|
||||||
|
// Clear current temp flags
|
||||||
|
gSaveContext.respawn[RESPAWN_MODE_RETURN].tempSwchFlags = 0;
|
||||||
|
gSaveContext.respawn[RESPAWN_MODE_RETURN].tempCollectFlags = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set the respawn flag for when we want to return from a grotto entrance
|
// Set the respawn flag for when we want to return from a grotto entrance
|
||||||
// Used for Sun's Song and Game Over, which usually don't restore saved position data
|
// Used for Sun's Song and Game Over, which usually don't restore saved position data
|
||||||
void Grotto_ForceGrottoReturn(void) {
|
void Grotto_ForceGrottoReturn(void) {
|
||||||
if (lastEntranceType == GROTTO_RETURN && Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
|
if (lastEntranceType == GROTTO_RETURN && (Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) || Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS))) {
|
||||||
gSaveContext.respawnFlag = 2;
|
gSaveContext.respawnFlag = 2;
|
||||||
gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams = 0x0DFF;
|
gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams = 0x0DFF;
|
||||||
gSaveContext.respawn[RESPAWN_MODE_RETURN].pos = grottoReturnTable[grottoId].pos;
|
gSaveContext.respawn[RESPAWN_MODE_RETURN].pos = grottoReturnTable[grottoId].pos;
|
||||||
@ -231,7 +246,7 @@ void Grotto_ForceGrottoReturn(void) {
|
|||||||
|
|
||||||
// Used for the DMT special voids, which usually don't restore saved position data
|
// Used for the DMT special voids, which usually don't restore saved position data
|
||||||
void Grotto_ForceRegularVoidOut(void) {
|
void Grotto_ForceRegularVoidOut(void) {
|
||||||
if (lastEntranceType == GROTTO_RETURN && Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
|
if (lastEntranceType == GROTTO_RETURN && (Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) || Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS))) {
|
||||||
gSaveContext.respawn[RESPAWN_MODE_DOWN] = gSaveContext.respawn[RESPAWN_MODE_RETURN];
|
gSaveContext.respawn[RESPAWN_MODE_DOWN] = gSaveContext.respawn[RESPAWN_MODE_RETURN];
|
||||||
gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0x0DFF;
|
gSaveContext.respawn[RESPAWN_MODE_DOWN].playerParams = 0x0DFF;
|
||||||
gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = grottoReturnTable[grottoId].pos;
|
gSaveContext.respawn[RESPAWN_MODE_DOWN].pos = grottoReturnTable[grottoId].pos;
|
||||||
@ -242,13 +257,26 @@ void Grotto_ForceRegularVoidOut(void) {
|
|||||||
// If returning to a FW point saved at a grotto exit, copy the FW data to the Grotto Return Point
|
// If returning to a FW point saved at a grotto exit, copy the FW data to the Grotto Return Point
|
||||||
// so that Sun's Song and Game Over will behave correctly
|
// so that Sun's Song and Game Over will behave correctly
|
||||||
void Grotto_SetupReturnInfoOnFWReturn(void) {
|
void Grotto_SetupReturnInfoOnFWReturn(void) {
|
||||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
|
if (Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) || Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS) &&
|
||||||
|
gSaveContext.fw.playerParams == 0x4FF) {
|
||||||
gSaveContext.respawn[RESPAWN_MODE_RETURN] = gSaveContext.respawn[RESPAWN_MODE_TOP];
|
gSaveContext.respawn[RESPAWN_MODE_RETURN] = gSaveContext.respawn[RESPAWN_MODE_TOP];
|
||||||
gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams = 0x0DFF;
|
gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams = 0x0DFF;
|
||||||
lastEntranceType = GROTTO_RETURN;
|
lastEntranceType = GROTTO_RETURN;
|
||||||
|
} else {
|
||||||
|
lastEntranceType = NOT_GROTTO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a scene transition is not overridden at all (i.e. guards throwing Link out / quitting game)
|
||||||
|
// the lastEntranceType must be cleared to avoid messing up savewarps and deathwarps.
|
||||||
|
// This does not apply to void out and other respawns, which should keep the lastEntranceType.
|
||||||
|
void Grotto_SanitizeEntranceType(void) {
|
||||||
|
if (!overridingNextEntrance && gSaveContext.respawnFlag == 0) {
|
||||||
|
lastEntranceType = NOT_GROTTO;
|
||||||
|
}
|
||||||
|
overridingNextEntrance = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the renamed entrance index based on the grotto contents and exit scene number
|
// Get the renamed entrance index based on the grotto contents and exit scene number
|
||||||
s16 Grotto_GetRenamedGrottoIndexFromOriginal(s8 content, s8 scene) {
|
s16 Grotto_GetRenamedGrottoIndexFromOriginal(s8 content, s8 scene) {
|
||||||
for (s16 index = 0; index < NUM_GROTTOS; index++) {
|
for (s16 index = 0; index < NUM_GROTTOS; index++) {
|
||||||
|
@ -25,8 +25,10 @@ void Grotto_InitExitAndLoadLists(void);
|
|||||||
void Grotto_SetExitOverride(s16 originalIndex, s16 overrideIndex);
|
void Grotto_SetExitOverride(s16 originalIndex, s16 overrideIndex);
|
||||||
void Grotto_SetLoadOverride(s16 originalIndex, s16 overrideIndex);
|
void Grotto_SetLoadOverride(s16 originalIndex, s16 overrideIndex);
|
||||||
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex);
|
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex);
|
||||||
|
void Grotto_ForceGrottoReturnOnSpecialEntrance(void);
|
||||||
void Grotto_ForceGrottoReturn(void);
|
void Grotto_ForceGrottoReturn(void);
|
||||||
void Grotto_ForceRegularVoidOut(void);
|
void Grotto_ForceRegularVoidOut(void);
|
||||||
|
void Grotto_SanitizeEntranceType(void);
|
||||||
s16 Grotto_GetRenamedGrottoIndexFromOriginal(s8 content, s8 scene);
|
s16 Grotto_GetRenamedGrottoIndexFromOriginal(s8 content, s8 scene);
|
||||||
|
|
||||||
#endif //_RANDO_GROTTO_H_
|
#endif //_RANDO_GROTTO_H_
|
||||||
|
@ -1992,6 +1992,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
|||||||
} else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) &&
|
} else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) &&
|
||||||
(textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) {
|
(textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) {
|
||||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId);
|
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId);
|
||||||
|
} else if (Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS) &&
|
||||||
|
(textId >= TEXT_WARP_MINUET_OF_FOREST && textId <= TEXT_WARP_PRELUDE_OF_LIGHT)) {
|
||||||
|
messageEntry = OTRGlobals::Instance->gRandomizer->GetWarpSongMessage(textId, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
|
if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) {
|
||||||
|
@ -175,6 +175,24 @@ void SaveManager::LoadRandomizerVersion2() {
|
|||||||
std::string ganonText;
|
std::string ganonText;
|
||||||
SaveManager::Instance->LoadData("ganonText", ganonText);
|
SaveManager::Instance->LoadData("ganonText", ganonText);
|
||||||
memcpy(gSaveContext.ganonText, ganonText.c_str(), ganonText.length());
|
memcpy(gSaveContext.ganonText, ganonText.c_str(), ganonText.length());
|
||||||
|
std::string warpMinuetText;
|
||||||
|
SaveManager::Instance->LoadData("warpMinuetText", warpMinuetText);
|
||||||
|
memcpy(gSaveContext.warpMinuetText, warpMinuetText.c_str(), warpMinuetText.length());
|
||||||
|
std::string warpBoleroText;
|
||||||
|
SaveManager::Instance->LoadData("warpBoleroText", warpBoleroText);
|
||||||
|
memcpy(gSaveContext.warpBoleroText, warpBoleroText.c_str(), warpBoleroText.length());
|
||||||
|
std::string warpSerenadeText;
|
||||||
|
SaveManager::Instance->LoadData("warpSerenadeText", warpSerenadeText);
|
||||||
|
memcpy(gSaveContext.warpSerenadeText, warpSerenadeText.c_str(), warpSerenadeText.length());
|
||||||
|
std::string warpRequiemText;
|
||||||
|
SaveManager::Instance->LoadData("warpRequiemText", warpRequiemText);
|
||||||
|
memcpy(gSaveContext.warpRequiemText, warpRequiemText.c_str(), warpRequiemText.length());
|
||||||
|
std::string warpNocturneText;
|
||||||
|
SaveManager::Instance->LoadData("warpNocturneText", warpNocturneText);
|
||||||
|
memcpy(gSaveContext.warpNocturneText, warpNocturneText.c_str(), warpNocturneText.length());
|
||||||
|
std::string warpPreludeText;
|
||||||
|
SaveManager::Instance->LoadData("warpPreludeText", warpPreludeText);
|
||||||
|
memcpy(gSaveContext.warpPreludeText, warpPreludeText.c_str(), warpPreludeText.length());
|
||||||
|
|
||||||
SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems);
|
SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems);
|
||||||
|
|
||||||
@ -246,6 +264,12 @@ void SaveManager::SaveRandomizer() {
|
|||||||
SaveManager::Instance->SaveData("adultAltarText", gSaveContext.adultAltarText);
|
SaveManager::Instance->SaveData("adultAltarText", gSaveContext.adultAltarText);
|
||||||
SaveManager::Instance->SaveData("ganonHintText", gSaveContext.ganonHintText);
|
SaveManager::Instance->SaveData("ganonHintText", gSaveContext.ganonHintText);
|
||||||
SaveManager::Instance->SaveData("ganonText", gSaveContext.ganonText);
|
SaveManager::Instance->SaveData("ganonText", gSaveContext.ganonText);
|
||||||
|
SaveManager::Instance->SaveData("warpMinuetText", gSaveContext.warpMinuetText);
|
||||||
|
SaveManager::Instance->SaveData("warpBoleroText", gSaveContext.warpBoleroText);
|
||||||
|
SaveManager::Instance->SaveData("warpSerenadeText", gSaveContext.warpSerenadeText);
|
||||||
|
SaveManager::Instance->SaveData("warpRequiemText", gSaveContext.warpRequiemText);
|
||||||
|
SaveManager::Instance->SaveData("warpNocturneText", gSaveContext.warpNocturneText);
|
||||||
|
SaveManager::Instance->SaveData("warpPreludeText", gSaveContext.warpPreludeText);
|
||||||
|
|
||||||
SaveManager::Instance->SaveData("adultTradeItems", gSaveContext.adultTradeItems);
|
SaveManager::Instance->SaveData("adultTradeItems", gSaveContext.adultTradeItems);
|
||||||
|
|
||||||
|
@ -200,14 +200,6 @@ void Sram_OpenSave() {
|
|||||||
// Setup the modified entrance table and entrance shuffle table for rando
|
// Setup the modified entrance table and entrance shuffle table for rando
|
||||||
if (gSaveContext.n64ddFlag) {
|
if (gSaveContext.n64ddFlag) {
|
||||||
Entrance_Init();
|
Entrance_Init();
|
||||||
if (!CVar_GetS32("gRememberSaveLocation", 0) || gSaveContext.savedSceneNum == SCENE_YOUSEI_IZUMI_TATE ||
|
|
||||||
gSaveContext.savedSceneNum == SCENE_KAKUSIANA) {
|
|
||||||
Entrance_SetSavewarpEntrance();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// When going from a rando save to a vanilla save within the same game instance
|
|
||||||
// we need to reset the entrance table back to its vanilla state
|
|
||||||
Entrance_ResetEntranceTable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
osSyncPrintf("scene_no = %d\n", gSaveContext.entranceIndex);
|
osSyncPrintf("scene_no = %d\n", gSaveContext.entranceIndex);
|
||||||
@ -390,11 +382,18 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
|||||||
break;
|
break;
|
||||||
case RO_AGE_CHILD: //Child
|
case RO_AGE_CHILD: //Child
|
||||||
gSaveContext.linkAge = 1;
|
gSaveContext.linkAge = 1;
|
||||||
|
gSaveContext.savedSceneNum = -1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS)) {
|
||||||
|
// Override the spawn entrance so entrance rando can take control,
|
||||||
|
// and to prevent remember save location from breaking inital spawn
|
||||||
|
gSaveContext.entranceIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME);
|
int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME);
|
||||||
switch (doorOfTime) {
|
switch (doorOfTime) {
|
||||||
case RO_DOOROFTIME_OPEN:
|
case RO_DOOROFTIME_OPEN:
|
||||||
@ -580,4 +579,8 @@ void Sram_InitSram(GameState* gameState) {
|
|||||||
Save_Init();
|
Save_Init();
|
||||||
|
|
||||||
func_800F6700(gSaveContext.audioSetting);
|
func_800F6700(gSaveContext.audioSetting);
|
||||||
|
|
||||||
|
// When going from a rando save to a vanilla save within the same game instance
|
||||||
|
// we need to reset the entrance table back to its vanilla state
|
||||||
|
Entrance_ResetEntranceTable();
|
||||||
}
|
}
|
||||||
|
@ -425,6 +425,11 @@ void DemoKankyo_KillDoorOfTimeCollision(DemoKankyo* this, PlayState* play) {
|
|||||||
void DemoKankyo_Update(Actor* thisx, PlayState* play) {
|
void DemoKankyo_Update(Actor* thisx, PlayState* play) {
|
||||||
DemoKankyo* this = (DemoKankyo*)thisx;
|
DemoKankyo* this = (DemoKankyo*)thisx;
|
||||||
this->actionFunc(this, play);
|
this->actionFunc(this, play);
|
||||||
|
|
||||||
|
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS) &&
|
||||||
|
thisx->params == 0x000F) { // Warp Song particles
|
||||||
|
Entrance_SetWarpSongEntrance();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemoKankyo_Draw(Actor* thisx, PlayState* play) {
|
void DemoKankyo_Draw(Actor* thisx, PlayState* play) {
|
||||||
|
@ -958,7 +958,11 @@ void func_80ACC00C(EnOwl* this, PlayState* play) {
|
|||||||
osSyncPrintf("SPOT 06 の デモがはしった\n"); // "Demo of SPOT 06 has been completed"
|
osSyncPrintf("SPOT 06 の デモがはしった\n"); // "Demo of SPOT 06 has been completed"
|
||||||
osSyncPrintf(VT_RST);
|
osSyncPrintf(VT_RST);
|
||||||
if (gSaveContext.n64ddFlag) {
|
if (gSaveContext.n64ddFlag) {
|
||||||
|
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OWL_DROPS)) {
|
||||||
|
play->nextEntranceIndex = Entrance_OverrideNextIndex(0x027E);
|
||||||
|
} else {
|
||||||
play->nextEntranceIndex = 0x027E;
|
play->nextEntranceIndex = 0x027E;
|
||||||
|
}
|
||||||
play->sceneLoadFlag = 0x14;
|
play->sceneLoadFlag = 0x14;
|
||||||
play->fadeTransition = 2;
|
play->fadeTransition = 2;
|
||||||
break;
|
break;
|
||||||
@ -969,7 +973,11 @@ void func_80ACC00C(EnOwl* this, PlayState* play) {
|
|||||||
case 8:
|
case 8:
|
||||||
case 9:
|
case 9:
|
||||||
if (gSaveContext.n64ddFlag) {
|
if (gSaveContext.n64ddFlag) {
|
||||||
|
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OWL_DROPS)) {
|
||||||
|
play->nextEntranceIndex = Entrance_OverrideNextIndex(0x0554);
|
||||||
|
} else {
|
||||||
play->nextEntranceIndex = 0x0554;
|
play->nextEntranceIndex = 0x0554;
|
||||||
|
}
|
||||||
play->sceneLoadFlag = 0x14;
|
play->sceneLoadFlag = 0x14;
|
||||||
play->fadeTransition = 2;
|
play->fadeTransition = 2;
|
||||||
break;
|
break;
|
||||||
|
@ -9591,6 +9591,11 @@ void Player_Init(Actor* thisx, PlayState* play2) {
|
|||||||
s32 sp50;
|
s32 sp50;
|
||||||
s32 sp4C;
|
s32 sp4C;
|
||||||
|
|
||||||
|
// In ER, once Link has spawned we know the scene has loaded, so we can sanitize the last known entrance type
|
||||||
|
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) {
|
||||||
|
Grotto_SanitizeEntranceType();
|
||||||
|
}
|
||||||
|
|
||||||
play->shootingGalleryStatus = play->bombchuBowlingStatus = 0;
|
play->shootingGalleryStatus = play->bombchuBowlingStatus = 0;
|
||||||
|
|
||||||
play->playerInit = Player_InitCommon;
|
play->playerInit = Player_InitCommon;
|
||||||
|
@ -2197,6 +2197,15 @@ void FileChoose_LoadGame(GameState* thisx) {
|
|||||||
gSaveContext.inventory.equipment ^= (gBitFlags[swordEquipMask - 1] << BOMSWAP16(gEquipShifts[EQUIP_SWORD]));
|
gSaveContext.inventory.equipment ^= (gBitFlags[swordEquipMask - 1] << BOMSWAP16(gEquipShifts[EQUIP_SWORD]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle randomized spawn positions after the save context has been setup from load
|
||||||
|
// When remeber save location is on, set save warp if the save was in an a grotto, or
|
||||||
|
// the entrance index is -1 from shuffle overwarld spawn
|
||||||
|
if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES) && ((!CVar_GetS32("gRememberSaveLocation", 0) ||
|
||||||
|
gSaveContext.savedSceneNum == SCENE_YOUSEI_IZUMI_TATE || gSaveContext.savedSceneNum == SCENE_KAKUSIANA) ||
|
||||||
|
(CVar_GetS32("gRememberSaveLocation", 0) && Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) && gSaveContext.entranceIndex == -1))) {
|
||||||
|
Entrance_SetSavewarpEntrance();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void (*gSelectModeUpdateFuncs[])(GameState*) = {
|
static void (*gSelectModeUpdateFuncs[])(GameState*) = {
|
||||||
|
Loading…
Reference in New Issue
Block a user