mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-01-30 23:10:14 -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 ganonHintText[150];
|
||||
/* */ char ganonText[250];
|
||||
/* */ char warpMinuetText[100];
|
||||
/* */ char warpBoleroText[100];
|
||||
/* */ char warpSerenadeText[100];
|
||||
/* */ char warpRequiemText[100];
|
||||
/* */ char warpNocturneText[100];
|
||||
/* */ char warpPreludeText[100];
|
||||
/* */ u8 seedIcons[5];
|
||||
/* */ u16 randomizerInf[9];
|
||||
/* */ u16 adultTradeItems;
|
||||
|
@ -28,6 +28,13 @@ typedef enum {
|
||||
TEXT_SCRUB_RANDOM_FREE = 0x9001,
|
||||
TEXT_SHOP_ITEM_RANDOM = 0x9100,
|
||||
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;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -570,6 +570,7 @@ const std::vector<PresetEntry> s6PresetEntries = {
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleDungeonReward", RO_DUNGEON_REWARDS_END_OF_DUNGEON),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleGanonBossKey", RO_GANON_BOSS_KEY_STARTWITH),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleKokiriSword", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeShuffleOverworldSpawns", RO_GENERIC_ON),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipChildStealth", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipChildZelda", 1),
|
||||
PRESET_ENTRY_S32("gRandomizeSkipEponaRace", 1),
|
||||
@ -674,7 +675,7 @@ const std::map<PresetType, PresetTypeDefinition> presetTypes = {
|
||||
{ RANDOMIZER_PRESET_S6, {
|
||||
"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" \
|
||||
"- 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" \
|
||||
"- Full adult trade sequence is shuffled instead of the selected 4\n" \
|
||||
"- Hint distribution no \"tournament\" mode, falling back to balanced",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,11 +21,15 @@ enum class EntranceType {
|
||||
WarpSong,
|
||||
Dungeon,
|
||||
GanonDungeon,
|
||||
DungeonReverse,
|
||||
Interior,
|
||||
InteriorReverse,
|
||||
SpecialInterior,
|
||||
GrottoGrave,
|
||||
GrottoGraveReverse,
|
||||
Overworld,
|
||||
Extra,
|
||||
Mixed,
|
||||
All,
|
||||
};
|
||||
|
||||
@ -40,6 +44,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Resets the glitchless condition for the entrance
|
||||
void SetCondition(ConditionFn newCondition) {
|
||||
conditions_met[0] = newCondition;
|
||||
}
|
||||
|
||||
bool GetConditionsMet() const {
|
||||
if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
return true;
|
||||
|
@ -296,7 +296,7 @@ std::vector<uint32_t> GetAccessibleLocations(const std::vector<uint32_t>& allowe
|
||||
entranceSphere.push_back(&exit);
|
||||
exit.AddToPool();
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +116,12 @@ Text childAltarText;
|
||||
Text adultAltarText;
|
||||
Text ganonText;
|
||||
Text ganonHintText;
|
||||
Text warpMinuetText;
|
||||
Text warpBoleroText;
|
||||
Text warpSerenadeText;
|
||||
Text warpRequiemText;
|
||||
Text warpNocturneText;
|
||||
Text warpPreludeText;
|
||||
|
||||
Text& GetChildAltarText() {
|
||||
return childAltarText;
|
||||
@ -133,6 +139,30 @@ Text& GetGanonHintText() {
|
||||
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) {
|
||||
|
||||
std::vector<uint32_t> alreadyChecked = {};
|
||||
@ -707,10 +737,49 @@ void CreateMerchantsHints() {
|
||||
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() {
|
||||
|
||||
CreateGanonText();
|
||||
CreateAltarText();
|
||||
CreateWarpSongTexts();
|
||||
|
||||
SPDLOG_DEBUG("\nNOW CREATING HINTS\n");
|
||||
const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value<uint8_t>()];
|
||||
|
@ -225,3 +225,10 @@ Text& GetChildAltarText();
|
||||
Text& GetAdultAltarText();
|
||||
Text& GetGanonText();
|
||||
Text& GetGanonHintText();
|
||||
|
||||
Text& GetWarpMinuetText();
|
||||
Text& GetWarpBoleroText();
|
||||
Text& GetWarpSerenadeText();
|
||||
Text& GetWarpRequiemText();
|
||||
Text& GetWarpNocturneText();
|
||||
Text& GetWarpPreludeText();
|
||||
|
@ -2,7 +2,10 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
using AreaKey = uint32_t;
|
||||
using HintKey = uint32_t;
|
||||
using ItemKey = uint32_t;
|
||||
using LocationKey = uint32_t;
|
||||
using AreaKey = uint32_t;
|
||||
|
||||
typedef enum {
|
||||
NONE,
|
||||
@ -1082,6 +1085,14 @@ typedef enum {
|
||||
//AREAS
|
||||
ROOT,
|
||||
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,
|
||||
KF_LINKS_HOUSE,
|
||||
KF_MIDOS_HOUSE,
|
||||
@ -1135,6 +1146,7 @@ typedef enum {
|
||||
HAUNTED_WASTELAND,
|
||||
WASTELAND_NEAR_COLOSSUS,
|
||||
DESERT_COLOSSUS,
|
||||
DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY,
|
||||
COLOSSUS_GREAT_FAIRY_FOUNTAIN,
|
||||
COLOSSUS_GROTTO,
|
||||
MARKET_ENTRANCE,
|
||||
@ -1173,6 +1185,7 @@ typedef enum {
|
||||
KAK_POTION_SHOP_FRONT,
|
||||
KAK_POTION_SHOP_BACK,
|
||||
KAK_ROOFTOP,
|
||||
KAK_IMPAS_ROOFTOP,
|
||||
KAK_BEHIND_GATE,
|
||||
KAK_BACKYARD,
|
||||
KAK_ODD_POTION_BUILDING,
|
||||
|
@ -264,25 +264,66 @@ void AreaTable_Init() {
|
||||
|
||||
areaTable[ROOT_EXITS] = Area("Root Exits", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KF_LINKS_HOUSE, {[]{return IsChild;}}),
|
||||
Entrance(TEMPLE_OF_TIME, {[]{return (CanPlay(PreludeOfLight) && CanLeaveForest) || 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) ||
|
||||
((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) ||
|
||||
Entrance(CHILD_SPAWN, {[]{return IsChild;}}),
|
||||
Entrance(ADULT_SPAWN, {[]{return IsAdult;}}),
|
||||
Entrance(MINUET_OF_FOREST_WARP, {[]{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) ||
|
||||
((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;},
|
||||
/*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(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) ||
|
||||
((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;},
|
||||
/*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(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) ||
|
||||
((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;},
|
||||
/*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(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) ||
|
||||
((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;},
|
||||
/*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(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) ||
|
||||
((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
|
||||
@ -330,10 +371,19 @@ void AreaTable_Init() {
|
||||
|
||||
namespace Areas {
|
||||
|
||||
static std::array<const uint32_t, 414> allAreas = {
|
||||
static std::array<const uint32_t, 424> allAreas = {
|
||||
ROOT,
|
||||
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,
|
||||
KF_LINKS_HOUSE,
|
||||
KF_MIDOS_HOUSE,
|
||||
@ -373,6 +423,7 @@ namespace Areas {
|
||||
KAK_POTION_SHOP_FRONT,
|
||||
KAK_POTION_SHOP_BACK,
|
||||
KAK_ROOFTOP,
|
||||
KAK_IMPAS_ROOFTOP,
|
||||
KAK_BEHIND_GATE,
|
||||
KAK_BACKYARD,
|
||||
KAK_ODD_POTION_BUILDING,
|
||||
@ -473,6 +524,7 @@ namespace Areas {
|
||||
HAUNTED_WASTELAND,
|
||||
WASTELAND_NEAR_COLOSSUS,
|
||||
DESERT_COLOSSUS,
|
||||
DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY,
|
||||
COLOSSUS_GREAT_FAIRY_FOUNTAIN,
|
||||
COLOSSUS_GROTTO,
|
||||
SPIRIT_TEMPLE_ENTRYWAY,
|
||||
|
@ -50,7 +50,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
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)));}}),
|
||||
});
|
||||
|
||||
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
|
||||
//EventAccess(&TimeTravel, {[]{return true;}}),
|
||||
}, {
|
||||
@ -111,7 +111,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
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;}}),
|
||||
@ -120,7 +120,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
EventAccess(&NutPot, {[]{return NutPot || CanBlastOrSmash;}}),
|
||||
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));}}),
|
||||
});
|
||||
|
||||
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
|
||||
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;}}),
|
||||
@ -155,7 +155,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
LocationAccess(MARKET_10_BIG_POES, {[]{return IsAdult && BigPoeKill;}}),
|
||||
LocationAccess(MARKET_GS_GUARD_HOUSE, {[]{return IsChild;}}),
|
||||
@ -164,7 +164,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
LocationAccess(MARKET_BAZAAR_ITEM_1, {[]{return true;}}),
|
||||
LocationAccess(MARKET_BAZAAR_ITEM_2, {[]{return true;}}),
|
||||
@ -179,7 +179,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
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)));}}),
|
||||
@ -188,7 +188,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
LocationAccess(MARKET_SHOOTING_GALLERY_REWARD, {[]{return IsChild;}}),
|
||||
}, {
|
||||
@ -196,7 +196,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
LocationAccess(MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, {[]{return CanPlayBowling;}}),
|
||||
LocationAccess(MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, {[]{return CanPlayBowling;}}),
|
||||
@ -206,7 +206,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
LocationAccess(MARKET_POTION_SHOP_ITEM_1, {[]{return true;}}),
|
||||
LocationAccess(MARKET_POTION_SHOP_ITEM_2, {[]{return true;}}),
|
||||
@ -221,7 +221,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
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));}}),
|
||||
@ -235,7 +235,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_1, {[]{return true;}}),
|
||||
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_2, {[]{return true;}}),
|
||||
@ -250,7 +250,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
LocationAccess(MARKET_LOST_DOG, {[]{return IsChild && AtNight;}}),
|
||||
}, {
|
||||
@ -258,7 +258,7 @@ void AreaTable_Init_CastleTown() {
|
||||
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
|
||||
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, {}, {}, {
|
||||
//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
|
||||
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)) ||
|
||||
@ -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
|
||||
LocationAccess(DMT_STORMS_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(DMT_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
@ -78,7 +78,7 @@ void AreaTable_Init_DeathMountain() {
|
||||
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
|
||||
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)) ||
|
||||
@ -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));}}),
|
||||
});
|
||||
|
||||
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
|
||||
LocationAccess(GC_SHOP_ITEM_1, {[]{return true;}}),
|
||||
LocationAccess(GC_SHOP_ITEM_2, {[]{return true;}}),
|
||||
@ -171,7 +171,7 @@ void AreaTable_Init_DeathMountain() {
|
||||
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
|
||||
LocationAccess(GC_DEKU_SCRUB_GROTTO_LEFT, {[]{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;}}),
|
||||
});
|
||||
|
||||
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
|
||||
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)) ||
|
||||
@ -272,7 +272,7 @@ void AreaTable_Init_DeathMountain() {
|
||||
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
|
||||
LocationAccess(DMC_UPPER_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(DMC_UPPER_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
@ -281,7 +281,7 @@ void AreaTable_Init_DeathMountain() {
|
||||
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
|
||||
LocationAccess(DMC_DEKU_SCRUB_GROTTO_LEFT, {[]{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);}}),
|
||||
});
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
LocationAccess(GV_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(GV_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||
@ -148,7 +148,7 @@ void AreaTable_Init_GerudoValley() {
|
||||
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
|
||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||
}, {}, {
|
||||
@ -200,7 +200,6 @@ void AreaTable_Init_GerudoValley() {
|
||||
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))) ||
|
||||
(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_TREE, {[]{return IsAdult && HookshotOrBoomerang && AtNight && 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);}}),
|
||||
});
|
||||
|
||||
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
|
||||
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;}}),
|
||||
@ -223,7 +230,7 @@ void AreaTable_Init_GerudoValley() {
|
||||
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
|
||||
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_REAR, {[]{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);}}),
|
||||
});
|
||||
|
||||
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
|
||||
LocationAccess(HF_SOUTHEAST_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(HF_SOUTHEAST_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
@ -48,7 +48,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
LocationAccess(HF_OPEN_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(HF_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
@ -57,7 +57,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
LocationAccess(HF_DEKU_SCRUB_GROTTO, {[]{return CanStunDeku;}}),
|
||||
}, {
|
||||
@ -65,7 +65,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
LocationAccess(HF_GS_COW_GROTTO, {[]{return HasFireSource && 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;}}),
|
||||
});
|
||||
|
||||
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
|
||||
LocationAccess(HF_NEAR_MARKET_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
@ -88,7 +88,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||
}, {}, {
|
||||
@ -96,7 +96,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
LocationAccess(HF_GS_NEAR_KAK_GROTTO, {[]{return HookshotOrBoomerang;}}),
|
||||
}, {
|
||||
@ -104,7 +104,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
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;}}),
|
||||
});
|
||||
|
||||
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
|
||||
EventAccess(&EyedropsAccess, {[]{return EyedropsAccess || (IsAdult && (EyeballFrogAccess || (EyeballFrog && DisableTradeRevert)));}}),
|
||||
}, {
|
||||
@ -182,7 +182,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
LocationAccess(LH_CHILD_FISHING, {[]{return IsChild;}}),
|
||||
LocationAccess(LH_ADULT_FISHING, {[]{return IsAdult;}}),
|
||||
@ -191,7 +191,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
LocationAccess(LH_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(LH_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
|
||||
@ -224,7 +224,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
LocationAccess(LLR_TALONS_CHICKENS, {[]{return IsChild && AtDay && ZeldasLetter;}}),
|
||||
}, {
|
||||
@ -232,7 +232,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
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;}}),
|
||||
@ -243,7 +243,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
LocationAccess(LLR_FREESTANDING_POH, {[]{return IsChild;}}),
|
||||
LocationAccess(LLR_TOWER_LEFT_COW, {[]{return CanPlay(EponasSong);},
|
||||
@ -255,7 +255,7 @@ void AreaTable_Init_HyruleField() {
|
||||
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
|
||||
LocationAccess(LLR_DEKU_SCRUB_GROTTO_LEFT, {[]{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_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)));}}),
|
||||
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
|
||||
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));}}),
|
||||
Entrance(KAK_ROOFTOP, {[]{return CanUse(HOOKSHOT) || (LogicManOnRoof && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(BOW) || CanUse(LONGSHOT)));},
|
||||
/*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(KAK_BEHIND_GATE, {[]{return IsAdult || (KakarikoVillageGateOpen);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
@ -56,6 +56,15 @@ void AreaTable_Init_Kakariko() {
|
||||
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, {}, {
|
||||
//Locations
|
||||
LocationAccess(KAK_MAN_ON_ROOF, {[]{return true;}}),
|
||||
@ -73,7 +82,7 @@ void AreaTable_Init_Kakariko() {
|
||||
/*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
|
||||
EventAccess(&WakeUpAdultTalon, {[]{return WakeUpAdultTalon || (IsAdult && PocketEgg);}}),
|
||||
}, {}, {
|
||||
@ -81,7 +90,7 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
LocationAccess(KAK_10_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 10;}}),
|
||||
LocationAccess(KAK_20_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 20;}}),
|
||||
@ -93,13 +102,13 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{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
|
||||
LocationAccess(KAK_IMPAS_HOUSE_FREESTANDING_POH, {[]{return true;}}),
|
||||
}, {
|
||||
@ -108,13 +117,13 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
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;}}),
|
||||
}, {});
|
||||
|
||||
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
|
||||
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)) &&
|
||||
@ -131,7 +140,7 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
LocationAccess(KAK_BAZAAR_ITEM_1, {[]{return true;}}),
|
||||
LocationAccess(KAK_BAZAAR_ITEM_2, {[]{return true;}}),
|
||||
@ -146,7 +155,7 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
LocationAccess(KAK_SHOOTING_GALLERY_REWARD, {[]{return IsAdult && Bow;}}),
|
||||
}, {
|
||||
@ -154,7 +163,7 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
LocationAccess(KAK_POTION_SHOP_ITEM_1, {[]{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;}}),
|
||||
});
|
||||
|
||||
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
|
||||
Entrance(KAK_BACKYARD, {[]{return IsAdult;}}),
|
||||
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
|
||||
EventAccess(&OddPoulticeAccess, {[]{return OddPoulticeAccess || (IsAdult && (OddMushroomAccess || (OddMushroom && DisableTradeRevert)));}}),
|
||||
}, {
|
||||
@ -186,7 +195,7 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
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;}}),
|
||||
});
|
||||
|
||||
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
|
||||
LocationAccess(KAK_OPEN_GROTTO_CHEST, {[]{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);}}),
|
||||
});
|
||||
|
||||
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
|
||||
LocationAccess(GRAVEYARD_SHIELD_GRAVE_CHEST, {[]{return true;}}),
|
||||
//Free Fairies
|
||||
@ -239,7 +248,7 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
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;}}),
|
||||
@ -248,7 +257,7 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
LocationAccess(GRAVEYARD_COMPOSERS_GRAVE_CHEST, {[]{return HasFireSource;},
|
||||
/*Glitched*/[]{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
@ -258,7 +267,7 @@ void AreaTable_Init_Kakariko() {
|
||||
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
|
||||
EventAccess(&NutPot, {[]{return true;}}),
|
||||
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;}}),
|
||||
});
|
||||
|
||||
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
|
||||
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);}}),
|
||||
});
|
||||
|
||||
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
|
||||
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;}}),
|
||||
@ -62,7 +62,7 @@ void AreaTable_Init_LostWoods() {
|
||||
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
|
||||
LocationAccess(KF_MIDOS_TOP_LEFT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(KF_MIDOS_TOP_RIGHT_CHEST, {[]{return true;}}),
|
||||
@ -73,22 +73,22 @@ void AreaTable_Init_LostWoods() {
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
LocationAccess(KF_SHOP_ITEM_1, {[]{return true;}}),
|
||||
LocationAccess(KF_SHOP_ITEM_2, {[]{return true;}}),
|
||||
@ -103,7 +103,7 @@ void AreaTable_Init_LostWoods() {
|
||||
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
|
||||
LocationAccess(KF_STORMS_GROTTO_CHEST, {[]{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);});}}),
|
||||
});
|
||||
|
||||
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
|
||||
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_CHEST, {[]{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;}}),
|
||||
});
|
||||
|
||||
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
|
||||
LocationAccess(DEKU_THEATER_SKULL_MASK, {[]{return IsChild && SkullMask;}}),
|
||||
LocationAccess(DEKU_THEATER_MASK_OF_TRUTH, {[]{return IsChild && MaskOfTruth;}}),
|
||||
@ -195,7 +195,7 @@ void AreaTable_Init_LostWoods() {
|
||||
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
|
||||
LocationAccess(LW_DEKU_SCRUB_GROTTO_REAR, {[]{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);}}),
|
||||
});
|
||||
|
||||
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
|
||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||
}, {}, {
|
||||
@ -240,7 +240,7 @@ void AreaTable_Init_LostWoods() {
|
||||
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
|
||||
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;}}),
|
||||
});
|
||||
|
||||
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
|
||||
LocationAccess(SFM_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(SFM_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||
|
@ -12,9 +12,9 @@ void AreaTable_Init_SpiritTemple() {
|
||||
---------------------------*/
|
||||
areaTable[SPIRIT_TEMPLE_ENTRYWAY] = Area("Spirit Temple Entryway", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(SPIRIT_TEMPLE_LOBBY, {[]{return Dungeon::SpiritTemple.IsVanilla();}}),
|
||||
Entrance(SPIRIT_TEMPLE_MQ_LOBBY, {[]{return Dungeon::SpiritTemple.IsMQ();}}),
|
||||
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
|
||||
Entrance(SPIRIT_TEMPLE_LOBBY, {[]{return Dungeon::SpiritTemple.IsVanilla();}}),
|
||||
Entrance(SPIRIT_TEMPLE_MQ_LOBBY, {[]{return Dungeon::SpiritTemple.IsMQ();}}),
|
||||
Entrance(DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
|
@ -76,7 +76,7 @@ void AreaTable_Init_ZorasDomain() {
|
||||
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
|
||||
LocationAccess(ZR_OPEN_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(ZR_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
@ -85,7 +85,7 @@ void AreaTable_Init_ZorasDomain() {
|
||||
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
|
||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||
}, {}, {
|
||||
@ -93,7 +93,7 @@ void AreaTable_Init_ZorasDomain() {
|
||||
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
|
||||
LocationAccess(ZR_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(ZR_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||
@ -142,7 +142,7 @@ void AreaTable_Init_ZorasDomain() {
|
||||
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
|
||||
LocationAccess(ZD_SHOP_ITEM_1, {[]{return true;}}),
|
||||
LocationAccess(ZD_SHOP_ITEM_2, {[]{return true;}}),
|
||||
@ -157,7 +157,7 @@ void AreaTable_Init_ZorasDomain() {
|
||||
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
|
||||
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)));}}),
|
||||
});
|
||||
|
||||
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
|
||||
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)) ||
|
||||
|
@ -194,6 +194,52 @@ string_view grottoEntrancesDesc = "Shuffle the pool of grotto entrances, i
|
||||
"all graves, small Fairy Fountains and the Lost\n" //
|
||||
"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 | //
|
||||
------------------------------*/ //
|
||||
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 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 interiorEntrancesSimple;
|
||||
extern string_view interiorEntrancesAll;
|
||||
|
@ -88,10 +88,19 @@ namespace Settings {
|
||||
Option StartingAge = Option::U8 ("Starting Age", {"Child", "Adult", "Random"}, {ageDesc}, OptionCategory::Setting, AGE_CHILD);
|
||||
uint8_t ResolvedStartingAge;
|
||||
Option ShuffleEntrances = Option::Bool("Shuffle Entrances", {"Off", "On"}, {shuffleEntrancesDesc});
|
||||
Option ShuffleDungeonEntrances = Option::U8 ("Dungeon Entrances", {"Off", "On", "On + Ganon"}, {dungeonEntrancesDesc});
|
||||
Option ShuffleOverworldEntrances = Option::Bool("Overworld Entrances", {"Off", "On"}, {overworldEntrancesDesc});
|
||||
Option ShuffleInteriorEntrances = Option::U8 ("Interior Entrances", {"Off", "Simple", "All"}, {interiorEntrancesOff, interiorEntrancesSimple, interiorEntrancesAll});
|
||||
Option ShuffleGrottoEntrances = Option::Bool("Grottos Entrances", {"Off", "On"}, {grottoEntrancesDesc});
|
||||
Option ShuffleDungeonEntrances = Option::U8 ("Dungeon Entrances", {"Off", "On", "On + Ganon"}, {dungeonEntrancesDesc});
|
||||
Option ShuffleOverworldEntrances = Option::Bool("Overworld Entrances", {"Off", "On"}, {overworldEntrancesDesc});
|
||||
Option ShuffleInteriorEntrances = Option::U8 ("Interior Entrances", {"Off", "Simple", "All"}, {interiorEntrancesOff, interiorEntrancesSimple, interiorEntrancesAll});
|
||||
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 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);
|
||||
@ -119,6 +128,15 @@ namespace Settings {
|
||||
&ShuffleOverworldEntrances,
|
||||
&ShuffleInteriorEntrances,
|
||||
&ShuffleGrottoEntrances,
|
||||
&ShuffleOwlDrops,
|
||||
&ShuffleWarpSongs,
|
||||
&ShuffleOverworldSpawns,
|
||||
&MixedEntrancePools,
|
||||
&MixDungeons,
|
||||
&MixOverworld,
|
||||
&MixInteriors,
|
||||
&MixGrottos,
|
||||
&DecoupleEntrances,
|
||||
&BombchusInLogic,
|
||||
&AmmoDrops,
|
||||
&HeartDropRefill,
|
||||
@ -1256,6 +1274,15 @@ namespace Settings {
|
||||
ctx.shuffleOverworldEntrances = (ShuffleOverworldEntrances) ? 1 : 0;
|
||||
ctx.shuffleInteriorEntrances = ShuffleInteriorEntrances.Value<uint8_t>();
|
||||
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.ammoDrops = AmmoDrops.Value<uint8_t>();
|
||||
ctx.heartDropRefill = HeartDropRefill.Value<uint8_t>();
|
||||
@ -1929,6 +1956,11 @@ namespace Settings {
|
||||
ShuffleOverworldEntrances.Unhide();
|
||||
ShuffleInteriorEntrances.Unhide();
|
||||
ShuffleGrottoEntrances.Unhide();
|
||||
ShuffleOwlDrops.Unhide();
|
||||
ShuffleWarpSongs.Unhide();
|
||||
ShuffleOverworldSpawns.Unhide();
|
||||
MixedEntrancePools.Unhide();
|
||||
DecoupleEntrances.Unhide();
|
||||
} else {
|
||||
ShuffleDungeonEntrances.SetSelectedIndex(SHUFFLEDUNGEONS_OFF);
|
||||
ShuffleDungeonEntrances.Hide();
|
||||
@ -1938,6 +1970,56 @@ namespace Settings {
|
||||
ShuffleInteriorEntrances.Hide();
|
||||
ShuffleGrottoEntrances.SetSelectedIndex(OFF);
|
||||
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);
|
||||
ShuffleInteriorEntrances.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
|
||||
@ -2569,6 +2663,15 @@ namespace Settings {
|
||||
ShuffleOverworldEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES]);
|
||||
ShuffleInteriorEntrances.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_INTERIOR_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
|
||||
// at the ranch, so we should *not* shuffle the weird egg
|
||||
|
@ -390,6 +390,15 @@ typedef struct {
|
||||
uint8_t shuffleOverworldEntrances;
|
||||
uint8_t shuffleInteriorEntrances;
|
||||
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 ammoDrops;
|
||||
uint8_t heartDropRefill;
|
||||
@ -897,6 +906,15 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
|
||||
extern Option ShuffleOverworldEntrances;
|
||||
extern Option ShuffleInteriorEntrances;
|
||||
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 AmmoDrops;
|
||||
extern Option HeartDropRefill;
|
||||
|
@ -298,41 +298,47 @@ static void WriteLocation(
|
||||
//Writes a shuffled entrance to the specified node
|
||||
static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance) {
|
||||
int16_t originalIndex = entrance->GetIndex();
|
||||
int16_t destinationIndex = entrance->GetReverse()->GetIndex();
|
||||
int16_t destinationIndex = -1;
|
||||
int16_t originalBlueWarp = entrance->GetBlueWarp();
|
||||
int16_t replacementBlueWarp = entrance->GetReplacement()->GetReverse()->GetBlueWarp();
|
||||
int16_t replacementBlueWarp = -1;
|
||||
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
||||
int16_t replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
||||
int16_t replacementDestinationIndex = -1;
|
||||
std::string name = entrance->GetName();
|
||||
std::string text = entrance->GetConnectedRegion()->regionName + " from " + entrance->GetReplacement()->GetParentRegion()->regionName;
|
||||
|
||||
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||
destinationIndex = entrance->GetReverse()->GetIndex();
|
||||
replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
||||
replacementBlueWarp = entrance->GetReplacement()->GetReverse()->GetBlueWarp();
|
||||
}
|
||||
|
||||
json entranceJson = json::object({
|
||||
{"index", originalIndex},
|
||||
{"destination", destinationIndex},
|
||||
{"blueWarp", originalBlueWarp},
|
||||
{"override", replacementIndex},
|
||||
{"overrideDestination", replacementDestinationIndex},
|
||||
});
|
||||
|
||||
jsonData["entrances"].push_back(entranceJson);
|
||||
|
||||
// When decoupled entrances is off, handle saving reverse entrances with blue warps
|
||||
if (entrance->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||
json reverseEntranceJson = json::object({
|
||||
{"index", replacementDestinationIndex},
|
||||
{"destination", replacementIndex},
|
||||
{"blueWarp", replacementBlueWarp},
|
||||
{"override", destinationIndex},
|
||||
{"overrideDestination", originalIndex},
|
||||
});
|
||||
|
||||
jsonData["entrances"].push_back(reverseEntranceJson);
|
||||
}
|
||||
|
||||
switch (gSaveContext.language) {
|
||||
case LANGUAGE_ENG:
|
||||
case LANGUAGE_FRA:
|
||||
default:
|
||||
json entranceJson = json::object({
|
||||
{"index", originalIndex},
|
||||
{"destination", destinationIndex},
|
||||
{"blueWarp", originalBlueWarp},
|
||||
{"override", replacementIndex},
|
||||
{"overrideDestination", replacementDestinationIndex},
|
||||
});
|
||||
|
||||
jsonData["entrances"].push_back(entranceJson);
|
||||
|
||||
// When decoupled entrances is off, handle saving reverse entrances with blue warps
|
||||
if (!false) { // RANDOTODO: add check for decoupled entrances
|
||||
json reverseEntranceJson = json::object({
|
||||
{"index", replacementDestinationIndex},
|
||||
{"destination", replacementIndex},
|
||||
{"blueWarp", replacementBlueWarp},
|
||||
{"override", destinationIndex},
|
||||
{"overrideDestination", originalIndex},
|
||||
});
|
||||
|
||||
jsonData["entrances"].push_back(reverseEntranceJson);
|
||||
}
|
||||
|
||||
jsonData["entrancesMap"][sphereString][name] = text;
|
||||
break;
|
||||
}
|
||||
@ -628,12 +634,24 @@ static void WriteHints(int language) {
|
||||
default:
|
||||
unformattedGanonText = GetGanonText().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["adultAltarText"] = GetAdultAltarText().GetEnglish();
|
||||
break;
|
||||
case 2:
|
||||
unformattedGanonText = GetGanonText().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["adultAltarText"] = GetAdultAltarText().GetFrench();
|
||||
break;
|
||||
|
@ -224,6 +224,15 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
|
||||
{ "World Settings:Overworld Entrances", RSK_SHUFFLE_OVERWORLD_ENTRANCES },
|
||||
{ "World Settings:Interior Entrances", RSK_SHUFFLE_INTERIOR_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:Hint Clarity", RSK_HINT_CLARITY },
|
||||
{ "Misc Settings:Hint Distribution", RSK_HINT_DISTRIBUTION },
|
||||
@ -327,6 +336,12 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
|
||||
CustomMessageManager::Instance->CreateMessage(
|
||||
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 = {
|
||||
@ -716,6 +731,15 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
||||
case RSK_SHUFFLE_ENTRANCES:
|
||||
case RSK_SHUFFLE_OVERWORLD_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") {
|
||||
gSaveContext.randoSettings[index].value = RO_GENERIC_OFF;
|
||||
} 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);
|
||||
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"];
|
||||
int index = 0;
|
||||
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.
|
||||
cvarSettings[RSK_SHUFFLE_ENTRANCES] = CVar_GetS32("gRandomizeShuffleDungeonsEntrances", 0) ||
|
||||
CVar_GetS32("gRandomizeShuffleOverworldEntrances", 0) ||
|
||||
CVar_GetS32("gRandomizeShuffleInteriorsEntrances", 0) ||
|
||||
CVar_GetS32("gRandomizeShuffleGrottosEntrances", 0);
|
||||
cvarSettings[RSK_SHUFFLE_ENTRANCES] = CVar_GetS32("gRandomizeShuffleDungeonsEntrances", RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) ||
|
||||
CVar_GetS32("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF) ||
|
||||
CVar_GetS32("gRandomizeShuffleInteriorsEntrances", RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) ||
|
||||
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_OVERWORLD_ENTRANCES] = CVar_GetS32("gRandomizeShuffleOverworldEntrances", 0);
|
||||
cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES] = CVar_GetS32("gRandomizeShuffleInteriorsEntrances", 0);
|
||||
cvarSettings[RSK_SHUFFLE_GROTTO_ENTRANCES] = CVar_GetS32("gRandomizeShuffleGrottosEntrances", 0);
|
||||
cvarSettings[RSK_SHUFFLE_DUNGEON_ENTRANCES] = CVar_GetS32("gRandomizeShuffleDungeonsEntrances", RO_DUNGEON_ENTRANCE_SHUFFLE_OFF);
|
||||
cvarSettings[RSK_SHUFFLE_OVERWORLD_ENTRANCES] = CVar_GetS32("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF);
|
||||
cvarSettings[RSK_SHUFFLE_INTERIOR_ENTRANCES] = CVar_GetS32("gRandomizeShuffleInteriorsEntrances", RO_INTERIOR_ENTRANCE_SHUFFLE_OFF);
|
||||
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
|
||||
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."
|
||||
);
|
||||
|
||||
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::EndChild();
|
||||
ImGui::EndTable();
|
||||
@ -4016,6 +4158,47 @@ void DrawRandoEditor(bool& open) {
|
||||
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 messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId);
|
||||
RandomizerCheck rc = GetCheckFromRandomizerInf(randomizerInf);
|
||||
|
@ -77,6 +77,7 @@ class Randomizer {
|
||||
GetItemID GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId);
|
||||
ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck);
|
||||
ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck);
|
||||
CustomMessageEntry GetWarpSongMessage(u16 textId, bool mysterious = false);
|
||||
CustomMessageEntry GetMerchantMessage(RandomizerInf randomizerInf, u16 textId, bool mysterious = false);
|
||||
CustomMessageEntry GetMapGetItemMessageWithHint(GetItemEntry itemEntry);
|
||||
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) {
|
||||
if (!hasCopiedEntranceTable) {
|
||||
memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * 1556);
|
||||
@ -91,6 +99,7 @@ void Entrance_Init(void) {
|
||||
}
|
||||
|
||||
Entrance_SeparateOGCFairyFountainExit();
|
||||
Entrance_SeparateAdultSpawnAndPrelude();
|
||||
|
||||
// Initialize the entrance override table with each index leading to itself. An
|
||||
// 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
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -279,15 +288,58 @@ void Entrance_SetSavewarpEntrance(void) {
|
||||
} else if (scene == SCENE_GERUDOWAY) { // Theives hideout
|
||||
gSaveContext.entranceIndex = 0x0486; // Gerudo Fortress -> Thieve's Hideout spawn 0
|
||||
} 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) {
|
||||
gSaveContext.entranceIndex = Entrance_GetOverride(LINK_HOUSE_SAVEWARP_ENTRANCE);
|
||||
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); // Child Overworld Spawn
|
||||
} 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) {
|
||||
// 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) {
|
||||
case SCENE_YDAN_BOSS: // Ghoma boss room
|
||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(0x0457);
|
||||
@ -322,6 +374,8 @@ void Entrance_OverrideCutsceneEntrance(u16 cutsceneCmd) {
|
||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(newJabuJabusBellyEntrance);
|
||||
gPlayState->sceneLoadFlag = 0x14;
|
||||
gPlayState->fadeTransition = 2;
|
||||
// In case Jabu's mouth leads to a grotto return
|
||||
Grotto_ForceGrottoReturnOnSpecialEntrance();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -506,7 +560,7 @@ void Entrance_OverrideGeurdoGuardCapture(void) {
|
||||
}
|
||||
|
||||
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
|
||||
if (sceneNum == 95 && spawn == 1) {
|
||||
gPlayState->linkActorEntry->pos.x = 0x033A;
|
||||
|
@ -40,6 +40,7 @@ int16_t Entrance_OverrideNextIndex(int16_t nextEntranceIndex);
|
||||
int16_t Entrance_OverrideDynamicExit(int16_t dynamicExitIndex);
|
||||
uint32_t Entrance_SceneAndSpawnAre(uint8_t scene, uint8_t spawn);
|
||||
void Entrance_SetSavewarpEntrance(void);
|
||||
void Entrance_SetWarpSongEntrance(void);
|
||||
void Entrance_OverrideBlueWarp(void);
|
||||
void Entrance_OverrideCutsceneEntrance(uint16_t cutsceneCmd);
|
||||
void Entrance_HandleEponaState(void);
|
||||
|
@ -87,6 +87,7 @@ static s16 grottoExitList[NUM_GROTTOS] = {0};
|
||||
static s16 grottoLoadList[NUM_GROTTOS] = {0};
|
||||
static s8 grottoId = 0xFF;
|
||||
static s8 lastEntranceType = NOT_GROTTO;
|
||||
static u8 overridingNextEntrance = false;
|
||||
|
||||
// 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
|
||||
@ -111,24 +112,20 @@ void Grotto_SetLoadOverride(s16 originalIndex, s16 overrideIndex) {
|
||||
}
|
||||
|
||||
static void Grotto_SetupReturnInfo(GrottoReturnInfo grotto, RespawnMode respawnMode) {
|
||||
// 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].roomIndex = grotto.room;
|
||||
|
||||
if (false /*mixGrottos == ON*/ || false /*decoupledEntrances == ON*/) {
|
||||
// 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].roomIndex = grotto.room;
|
||||
gSaveContext.respawn[respawnMode].playerParams = 0x04FF; // exiting grotto with no initial camera focus
|
||||
}
|
||||
|
||||
gSaveContext.respawn[respawnMode].yaw = grotto.angle;
|
||||
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 (false /*mixGrottos == ON*/ || false /*decoupledEntrances == ON*/) {
|
||||
gSaveContext.respawn[respawnMode].tempSwchFlags = 0;
|
||||
gSaveContext.respawn[respawnMode].tempCollectFlags = 0;
|
||||
} else {
|
||||
gSaveContext.respawn[respawnMode].tempSwchFlags = gSaveContext.respawn[RESPAWN_MODE_RETURN].tempSwchFlags;
|
||||
gSaveContext.respawn[respawnMode].tempCollectFlags = gSaveContext.respawn[RESPAWN_MODE_RETURN].tempCollectFlags;
|
||||
}
|
||||
gSaveContext.respawn[respawnMode].yaw = grotto.angle;
|
||||
gSaveContext.respawn[respawnMode].pos = grotto.pos;
|
||||
// If Mixed Entrance Pools or decoupled entrances are active, set these flags to 0 instead of restoring them
|
||||
if (Randomizer_GetSettingValue(RSK_MIX_GROTTO_ENTRANCES) || Randomizer_GetSettingValue(RSK_DECOUPLED_ENTRANCES)) {
|
||||
gSaveContext.respawn[respawnMode].tempSwchFlags = 0;
|
||||
gSaveContext.respawn[respawnMode].tempCollectFlags = 0;
|
||||
} else {
|
||||
gSaveContext.respawn[respawnMode].tempSwchFlags = gSaveContext.respawn[RESPAWN_MODE_RETURN].tempSwchFlags;
|
||||
gSaveContext.respawn[respawnMode].tempCollectFlags = gSaveContext.respawn[RESPAWN_MODE_RETURN].tempCollectFlags;
|
||||
}
|
||||
}
|
||||
|
||||
// Translates and overrides the passed in entrance index if it corresponds to a
|
||||
@ -136,7 +133,7 @@ static void Grotto_SetupReturnInfo(GrottoReturnInfo grotto, RespawnMode respawnM
|
||||
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -157,13 +154,18 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
||||
Grotto_SetupReturnInfo(grotto, RESPAWN_MODE_RETURN);
|
||||
Grotto_SetupReturnInfo(grotto, RESPAWN_MODE_DOWN);
|
||||
|
||||
// When the nextEntranceIndex is determined by a dynamic exit, we have
|
||||
// to set the respawn information and nextEntranceIndex manually
|
||||
// When the nextEntranceIndex is determined by a dynamic exit,
|
||||
// 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) {
|
||||
gSaveContext.respawnFlag = 2;
|
||||
nextEntranceIndex = grotto.entranceIndex;
|
||||
gPlayState->fadeTransition = 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
|
||||
} else {
|
||||
nextEntranceIndex = 0x7FFF;
|
||||
@ -185,6 +187,7 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
||||
lastEntranceType = NOT_GROTTO;
|
||||
}
|
||||
|
||||
overridingNextEntrance = true;
|
||||
return nextEntranceIndex;
|
||||
}
|
||||
|
||||
@ -192,8 +195,8 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
||||
// thisx - pointer to the grotto actor
|
||||
void Grotto_OverrideActorEntrance(Actor* thisx) {
|
||||
|
||||
// Vanilla Behavior if grottos aren't shuffled
|
||||
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES)) {
|
||||
// Vanilla Behavior if there's no possibility of ending up in a grotto randomly
|
||||
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) && !Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) && !Randomizer_GetSettingValue(RSK_SHUFFLE_WARP_SONGS)) {
|
||||
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
|
||||
// Used for Sun's Song and Game Over, which usually don't restore saved position data
|
||||
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.respawn[RESPAWN_MODE_RETURN].playerParams = 0x0DFF;
|
||||
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
|
||||
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].playerParams = 0x0DFF;
|
||||
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
|
||||
// so that Sun's Song and Game Over will behave correctly
|
||||
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].playerParams = 0x0DFF;
|
||||
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
|
||||
s16 Grotto_GetRenamedGrottoIndexFromOriginal(s8 content, s8 scene) {
|
||||
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_SetLoadOverride(s16 originalIndex, s16 overrideIndex);
|
||||
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex);
|
||||
void Grotto_ForceGrottoReturnOnSpecialEntrance(void);
|
||||
void Grotto_ForceGrottoReturn(void);
|
||||
void Grotto_ForceRegularVoidOut(void);
|
||||
void Grotto_SanitizeEntranceType(void);
|
||||
s16 Grotto_GetRenamedGrottoIndexFromOriginal(s8 content, s8 scene);
|
||||
|
||||
#endif //_RANDO_GROTTO_H_
|
||||
|
@ -1992,6 +1992,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
||||
} else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) &&
|
||||
(textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) {
|
||||
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) {
|
||||
|
@ -175,6 +175,24 @@ void SaveManager::LoadRandomizerVersion2() {
|
||||
std::string ganonText;
|
||||
SaveManager::Instance->LoadData("ganonText", ganonText);
|
||||
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);
|
||||
|
||||
@ -246,6 +264,12 @@ void SaveManager::SaveRandomizer() {
|
||||
SaveManager::Instance->SaveData("adultAltarText", gSaveContext.adultAltarText);
|
||||
SaveManager::Instance->SaveData("ganonHintText", gSaveContext.ganonHintText);
|
||||
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);
|
||||
|
||||
|
@ -200,14 +200,6 @@ void Sram_OpenSave() {
|
||||
// Setup the modified entrance table and entrance shuffle table for rando
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
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);
|
||||
@ -390,11 +382,18 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
||||
break;
|
||||
case RO_AGE_CHILD: //Child
|
||||
gSaveContext.linkAge = 1;
|
||||
gSaveContext.savedSceneNum = -1;
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
switch (doorOfTime) {
|
||||
case RO_DOOROFTIME_OPEN:
|
||||
@ -580,4 +579,8 @@ void Sram_InitSram(GameState* gameState) {
|
||||
Save_Init();
|
||||
|
||||
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) {
|
||||
DemoKankyo* this = (DemoKankyo*)thisx;
|
||||
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) {
|
||||
|
@ -958,7 +958,11 @@ void func_80ACC00C(EnOwl* this, PlayState* play) {
|
||||
osSyncPrintf("SPOT 06 の デモがはしった\n"); // "Demo of SPOT 06 has been completed"
|
||||
osSyncPrintf(VT_RST);
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
play->nextEntranceIndex = 0x027E;
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OWL_DROPS)) {
|
||||
play->nextEntranceIndex = Entrance_OverrideNextIndex(0x027E);
|
||||
} else {
|
||||
play->nextEntranceIndex = 0x027E;
|
||||
}
|
||||
play->sceneLoadFlag = 0x14;
|
||||
play->fadeTransition = 2;
|
||||
break;
|
||||
@ -969,7 +973,11 @@ void func_80ACC00C(EnOwl* this, PlayState* play) {
|
||||
case 8:
|
||||
case 9:
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
play->nextEntranceIndex = 0x0554;
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OWL_DROPS)) {
|
||||
play->nextEntranceIndex = Entrance_OverrideNextIndex(0x0554);
|
||||
} else {
|
||||
play->nextEntranceIndex = 0x0554;
|
||||
}
|
||||
play->sceneLoadFlag = 0x14;
|
||||
play->fadeTransition = 2;
|
||||
break;
|
||||
|
@ -9591,6 +9591,11 @@ void Player_Init(Actor* thisx, PlayState* play2) {
|
||||
s32 sp50;
|
||||
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->playerInit = Player_InitCommon;
|
||||
|
@ -2197,6 +2197,15 @@ void FileChoose_LoadGame(GameState* thisx) {
|
||||
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*) = {
|
||||
|
Loading…
Reference in New Issue
Block a user