Merge remote-tracking branch 'upstream/develop-rando' into soulcalibur

This commit is contained in:
Ralphie Morell
2023-10-19 21:20:43 -04:00
88 changed files with 12052 additions and 11659 deletions

View File

@@ -7,6 +7,7 @@
#include "z64collision_check.h"
#include "z64bgcheck.h"
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
#include "z64actor_enum.h"
#define ACTOR_NUMBER_MAX 2000
#define INVISIBLE_ACTOR_MAX 20
@@ -337,22 +338,6 @@ typedef enum {
} ActorCategory;
//#define DEFINE_ACTOR(_0, enum, _2) enum,
#define DEFINE_ACTOR_INTERNAL(_0, enum, _2) enum,
#define DEFINE_ACTOR_UNSET(enum) enum,
#define DEFINE_ACTOR(_0, enum, _2) DEFINE_ACTOR_INTERNAL(_0, enum, _2)
#ifdef __cplusplus
enum ActorID : int {
#else
enum ActorID {
#endif
#include "tables/actor_table.h"
/* 0x0192 */ ACTOR_ID_MAX // originally "ACTOR_DLF_MAX"
};
#undef DEFINE_ACTOR
#undef DEFINE_ACTOR_INTERNAL
#undef DEFINE_ACTOR_UNSET
typedef enum {
DOORLOCK_NORMAL,

View File

@@ -0,0 +1,19 @@
#pragma once
#ifndef Z64ACTOR_ENUM_H
#define Z64ACTOR_ENUM_H
#define DEFINE_ACTOR_INTERNAL(_0, enum, _2) enum,
#define DEFINE_ACTOR_UNSET(enum) enum,
#define DEFINE_ACTOR(_0, enum, _2) DEFINE_ACTOR_INTERNAL(_0, enum, _2)
enum ActorID {
#include "tables/actor_table.h"
/* 0x0192 */ ACTOR_ID_MAX // originally "ACTOR_DLF_MAX"
};
#undef DEFINE_ACTOR
#undef DEFINE_ACTOR_INTERNAL
#undef DEFINE_ACTOR_UNSET
#endif

View File

@@ -2,6 +2,8 @@
#define Z64SCENE_H
#include "command_macros_base.h"
#include "libultraship/libultra.h"
#include "z64math.h"
typedef struct {
/* 0x00 */ uintptr_t vromStart;

View File

@@ -0,0 +1,17 @@
#pragma once
#ifndef Z64SCENE_ENUM_H
#define Z64SCENE_ENUM_H
#define DEFINE_SCENE(_0, _1, enum, _3, _4, _5) enum,
#ifdef __cplusplus
enum SceneID : int {
#else
enum SceneID {
#endif
#include "tables/scene_table.h"
/* 0x6E */ SCENE_ID_MAX
};
#undef DEFINE_SCENE
#endif

View File

@@ -58,7 +58,7 @@ typedef enum {
#ifdef __cplusplus
typedef struct {
u16 giid;
uint16_t giid;
ItemID iid;
std::string english;
std::string german;

View File

@@ -3,8 +3,8 @@
#include <stdint.h>
#endif
#define CHEST_ANIM_SHORT 0
#define CHEST_ANIM_LONG 1
#define CHEST_ANIM_SHORT (int16_t)0
#define CHEST_ANIM_LONG (int16_t)1
/**
* Flag to indicate which type of Actor has given the player an item. ITEM_FROM_NPC by default,
@@ -30,7 +30,7 @@ typedef enum GetItemCategory {
} GetItemCategory;
#define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim, itemCategory, modIndex, getItemId) \
{ itemId, field, (chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1), textId, objectId, modIndex, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, NULL }
{ itemId, field, (int16_t)((chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1)), textId, objectId, modIndex, getItemId, drawId, true, ITEM_FROM_NPC, itemCategory, NULL }
#define GET_ITEM_NONE \
{ ITEM_NONE, 0, 0, 0, 0, 0, 0, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, NULL }
@@ -38,7 +38,7 @@ typedef enum GetItemCategory {
typedef struct PlayState PlayState;
typedef struct GetItemEntry GetItemEntry;
typedef void (*CustomDrawFunc)(PlayState* play, GetItemEntry* getItemEntry);
typedef void (*CustomDrawFunc)(PlayState*, GetItemEntry*);
typedef struct GetItemEntry {
/* 0x00 */ uint16_t itemId;
@@ -55,4 +55,4 @@ typedef struct GetItemEntry {
/* 0x10 */ uint16_t drawItemId; // Will be a copy of itemId unless the item is an ice trap. Needed for particles to function on ice traps.
/* 0x11 */ uint16_t drawModIndex; // Will be a copy of modIndex unless the item is an ice trap. Needed for particles to function on ice traps.
CustomDrawFunc drawFunc;
}; // size = 0x11
} GetItemEntry; // size = 0x11

File diff suppressed because it is too large Load Diff

View File

@@ -4,17 +4,18 @@
#include <string>
#include <vector>
#include "keys.hpp"
#include "../randomizerTypes.h"
namespace Dungeon {
class DungeonInfo {
public:
DungeonInfo(std::string name_, uint32_t hintKey_, uint32_t map_, uint32_t compass_, uint32_t smallKey_, uint32_t keyRing_, uint32_t bossKey_,
DungeonInfo(std::string name_, RandomizerHintTextKey hintKey_, RandomizerGet map_, RandomizerGet compass_, RandomizerGet smallKey_,
RandomizerGet keyRing_, RandomizerGet bossKey_,
uint8_t vanillaKeyCount_, uint8_t mqKeyCount_,
std::vector<uint32_t> vanillaLocations_,
std::vector<uint32_t> mqLocations_,
std::vector<uint32_t> sharedLocations_,
std::vector<uint32_t> bossRoomLocations_);
std::vector<RandomizerCheck> vanillaLocations_,
std::vector<RandomizerCheck> mqLocations_,
std::vector<RandomizerCheck> sharedLocations_,
std::vector<RandomizerCheck> bossRoomLocations_);
~DungeonInfo();
const std::string& GetName() const {
@@ -53,12 +54,12 @@ public:
return (masterQuest) ? mqKeyCount : vanillaKeyCount;
}
uint32_t GetHintKey() const;
uint32_t GetSmallKey() const;
uint32_t GetKeyRing() const;
uint32_t GetMap() const;
uint32_t GetCompass() const;
uint32_t GetBossKey() const;
RandomizerHintTextKey GetHintKey() const;
RandomizerGet GetSmallKey() const;
RandomizerGet GetKeyRing() const;
RandomizerGet GetMap() const;
RandomizerGet GetCompass() const;
RandomizerGet GetBossKey() const;
void PlaceVanillaMap();
void PlaceVanillaCompass();
@@ -66,27 +67,27 @@ public:
void PlaceVanillaSmallKeys();
// Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla)
std::vector<uint32_t> GetDungeonLocations() const;
std::vector<RandomizerCheck> GetDungeonLocations() const;
// Gets all dungeon locations (MQ + Vanilla)
std::vector<uint32_t> GetEveryLocation() const;
std::vector<RandomizerCheck> GetEveryLocation() const;
private:
std::string name;
uint32_t hintKey;
uint32_t map;
uint32_t compass;
uint32_t smallKey;
uint32_t keyRing;
uint32_t bossKey;
RandomizerHintTextKey hintKey;
RandomizerGet map;
RandomizerGet compass;
RandomizerGet smallKey;
RandomizerGet keyRing;
RandomizerGet bossKey;
uint8_t vanillaKeyCount;
uint8_t mqKeyCount;
bool masterQuest = false;
bool hasKeyRing = false;
std::vector<uint32_t> vanillaLocations;
std::vector<uint32_t> mqLocations;
std::vector<uint32_t> sharedLocations;
std::vector<uint32_t> bossRoomLocations;
std::vector<RandomizerCheck> vanillaLocations;
std::vector<RandomizerCheck> mqLocations;
std::vector<RandomizerCheck> sharedLocations;
std::vector<RandomizerCheck> bossRoomLocations;
};
extern DungeonInfo DekuTree;

View File

@@ -2,12 +2,12 @@
#include "fill.hpp"
#include "settings.hpp"
#include "item_list.hpp"
#include "item_pool.hpp"
#include "item_location.hpp"
#include "../context.h"
#include "spoiler_log.hpp"
#include "hints.hpp"
#include "location_access.hpp"
#include "soh/Enhancements/randomizer/static_data.h"
#include <vector>
#include <utility>
@@ -23,16 +23,16 @@ static int curNumRandomizedEntrances = 0;
typedef struct {
EntranceType type;
AreaKey parentRegion;
AreaKey connectedRegion;
RandomizerRegion parentRegion;
RandomizerRegion connectedRegion;
int16_t index;
int16_t blueWarp;
} EntranceLinkInfo;
EntranceLinkInfo NO_RETURN_ENTRANCE = {EntranceType::None, NONE, NONE, -1};
EntranceLinkInfo NO_RETURN_ENTRANCE = {EntranceType::None, RR_NONE, RR_NONE, -1};
typedef struct {
std::list<AreaKey> targetRegions;
std::list<RandomizerRegion> targetRegions;
std::list<EntranceType> allowedTypes;
} PriorityEntrance;
//primary, secondary
@@ -87,7 +87,7 @@ void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
forwardEntrance->SetDecoupled();
}
if (returnEntry.parentRegion != NONE) {
if (returnEntry.parentRegion != RR_NONE) {
Entrance* returnEntrance = AreaTable(returnEntry.parentRegion)->GetExit(returnEntry.connectedRegion);
returnEntrance->SetIndex(returnEntry.index);
returnEntrance->SetBlueWarp(returnEntry.blueWarp);
@@ -125,7 +125,7 @@ static std::vector<Entrance*> AssumeEntrancePool(std::vector<Entrance*>& entranc
return assumedPool;
}
static std::vector<Entrance*> BuildOneWayTargets(std::vector<EntranceType> typesToInclude, std::vector<std::pair<AreaKey, AreaKey>> exclude = {}/*, target_region_names*/) {
static std::vector<Entrance*> BuildOneWayTargets(std::vector<EntranceType> typesToInclude, std::vector<std::pair<RandomizerRegion, RandomizerRegion>> exclude = {}/*, target_region_names*/) {
std::vector<Entrance*> oneWayEntrances = {};
// Get all entrances of the specified type
for (EntranceType poolType : typesToInclude) {
@@ -133,7 +133,7 @@ static std::vector<Entrance*> BuildOneWayTargets(std::vector<EntranceType> types
}
// Filter out any that are passed in the exclusion list
FilterAndEraseFromPool(oneWayEntrances, [&exclude](Entrance* entrance){
std::pair<AreaKey, AreaKey> entranceBeingChecked (entrance->GetParentRegionKey(), entrance->GetConnectedRegionKey());
std::pair<RandomizerRegion, RandomizerRegion> entranceBeingChecked (entrance->GetParentRegionKey(), entrance->GetConnectedRegionKey());
return ElementInContainer(entranceBeingChecked, exclude);
});
@@ -152,7 +152,7 @@ static std::vector<Entrance*> BuildOneWayTargets(std::vector<EntranceType> types
//returns restrictive entrances and soft entrances in an array of size 2 (restrictive vector is index 0, soft is index 1)
static std::array<std::vector<Entrance*>, 2> SplitEntrancesByRequirements(std::vector<Entrance*>& entrancesToSplit, std::vector<Entrance*>& assumedEntrances) {
//First, disconnect all root assumed entrances and save which regions they were originally connected to, so we can reconnect them later
std::map<Entrance*, AreaKey> originalConnectedRegions = {};
std::map<Entrance*, RandomizerRegion> originalConnectedRegions = {};
std::set<Entrance*> entrancesToDisconnect = {};
for (Entrance* entrance : assumedEntrances) {
entrancesToDisconnect.insert(entrance);
@@ -165,7 +165,7 @@ static std::array<std::vector<Entrance*>, 2> SplitEntrancesByRequirements(std::v
//soft entrances are ones that can be accessed by both ages (child/adult) at both times of day (day/night)
//restrictive entrances are ones that do not meet this criteria
for (Entrance* entrance : entrancesToDisconnect) {
if (entrance->GetConnectedRegionKey() != NONE) {
if (entrance->GetConnectedRegionKey() != RR_NONE) {
originalConnectedRegions[entrance] = entrance->Disconnect();
}
}
@@ -175,9 +175,10 @@ static std::array<std::vector<Entrance*>, 2> SplitEntrancesByRequirements(std::v
Logic::LogicReset();
// Apply the effects of all advancement items to search for entrance accessibility
std::vector<ItemKey> items = FilterFromPool(ItemPool, [](const ItemKey i){ return ItemTable(i).IsAdvancement();});
for (ItemKey unplacedItem : items) {
ItemTable(unplacedItem).ApplyEffect();
std::vector<RandomizerGet> items =
FilterFromPool(ItemPool, [](const RandomizerGet i){ return Rando::StaticData::RetrieveItem(i).IsAdvancement();});
for (RandomizerGet unplacedItem : items) {
Rando::StaticData::RetrieveItem(unplacedItem).ApplyEffect();
}
// run a search to see what's accessible
GetAccessibleLocations({});
@@ -248,12 +249,12 @@ static void RestoreConnections(Entrance* entrance, Entrance* targetEntrance) {
}
static void DeleteTargetEntrance(Entrance* targetEntrance) {
if (targetEntrance->GetConnectedRegionKey() != NONE) {
if (targetEntrance->GetConnectedRegionKey() != RR_NONE) {
targetEntrance->Disconnect();
}
if (targetEntrance->GetParentRegionKey() != NONE) {
if (targetEntrance->GetParentRegionKey() != RR_NONE) {
targetEntrance->GetParentRegion()->RemoveExit(targetEntrance);
targetEntrance->SetParentRegion(NONE);
targetEntrance->SetParentRegion(RR_NONE);
}
}
@@ -282,9 +283,9 @@ static bool EntranceUnreachableAs(Entrance* entrance, uint8_t age, std::vector<E
return false;
} else if (type == EntranceType::OwlDrop) {
return age == AGE_ADULT;
} else if (type == EntranceType::Spawn && entrance->GetConnectedRegionKey() == KF_LINKS_HOUSE) {
} else if (type == EntranceType::Spawn && entrance->GetConnectedRegionKey() == RR_KF_LINKS_HOUSE) {
return age == AGE_ADULT;
} else if (type == EntranceType::Spawn && entrance->GetConnectedRegionKey() == TEMPLE_OF_TIME) {
} else if (type == EntranceType::Spawn && entrance->GetConnectedRegionKey() == RR_TEMPLE_OF_TIME) {
return age == AGE_CHILD;
}
@@ -377,9 +378,9 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
(entrancePlaced == nullptr || type == EntranceType::Interior || type == EntranceType::SpecialInterior)) {
//When cows are shuffled, ensure both Impa's House entrances are in the same hint area because the cow is reachable from both sides
if (Settings::ShuffleCows) {
auto impasHouseFrontHintRegion = GetHintRegionHintKey(KAK_IMPAS_HOUSE);
auto impasHouseBackHintRegion = GetHintRegionHintKey(KAK_IMPAS_HOUSE_BACK);
if (impasHouseFrontHintRegion != NONE && impasHouseBackHintRegion != NONE && impasHouseBackHintRegion != LINKS_POCKET && impasHouseFrontHintRegion != LINKS_POCKET && impasHouseBackHintRegion != impasHouseFrontHintRegion) {
auto impasHouseFrontHintRegion = GetHintRegionHintKey(RR_KAK_IMPAS_HOUSE);
auto impasHouseBackHintRegion = GetHintRegionHintKey(RR_KAK_IMPAS_HOUSE_BACK);
if (impasHouseFrontHintRegion != RHT_NONE && impasHouseBackHintRegion != RHT_NONE && impasHouseBackHintRegion != RHT_LINKS_POCKET && impasHouseFrontHintRegion != RHT_LINKS_POCKET && impasHouseBackHintRegion != impasHouseFrontHintRegion) {
auto message = "Kak Impas House entrances are not in the same hint area\n";
SPDLOG_DEBUG(message);
return false;
@@ -388,10 +389,10 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
}
// If all locations aren't reachable, that means that one of the conditions failed when searching
if (!allLocationsReachable) {
if (!Rando::Context::GetInstance()->allLocationsReachable) {
if (checkOtherEntranceAccess) {
// At least one valid starting region with all basic refills should be reachable without using any items at the beginning of the seed
if (!AreaTable(KOKIRI_FOREST)->HasAccess() && !AreaTable(KAKARIKO_VILLAGE)->HasAccess()) {
if (!AreaTable(RR_KOKIRI_FOREST)->HasAccess() && !AreaTable(RR_KAKARIKO_VILLAGE)->HasAccess()) {
SPDLOG_DEBUG("Invalid starting area\n");
return false;
}
@@ -404,10 +405,10 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
// The player should be able to get back to ToT after going through time, without having collected any items
// This is important to ensure that the player never loses access to the pedestal after going through time
if (Settings::ResolvedStartingAge == AGE_CHILD && !AreaTable(TEMPLE_OF_TIME)->Adult()) {
if (Settings::ResolvedStartingAge == AGE_CHILD && !AreaTable(RR_TEMPLE_OF_TIME)->Adult()) {
SPDLOG_DEBUG("Path to Temple of Time as adult is not guaranteed\n");
return false;
} else if (Settings::ResolvedStartingAge == AGE_ADULT && !AreaTable(TEMPLE_OF_TIME)->Child()) {
} else if (Settings::ResolvedStartingAge == AGE_ADULT && !AreaTable(RR_TEMPLE_OF_TIME)->Child()) {
SPDLOG_DEBUG("Path to Temple of Time as child is not guaranteed\n");
return false;
}
@@ -416,7 +417,7 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
// The Big Poe shop should always be accessible as adult without the need to use any bottles
// This is important to ensure that players can never lock their only bottles by filling them with Big Poes they can't sell
if (checkPoeCollectorAccess) {
if (!AreaTable(MARKET_GUARD_HOUSE)->Adult()) {
if (!AreaTable(RR_MARKET_GUARD_HOUSE)->Adult()) {
SPDLOG_DEBUG("Big Poe Shop access is not guarenteed as adult\n");
return false;
}
@@ -451,7 +452,7 @@ static bool ReplaceEntrance(Entrance* entrance, Entrance* target, std::vector<En
//SPDLOG_DEBUG(message);
//Areas::DumpWorldGraph(ticks);
#endif
if (entrance->GetConnectedRegionKey() != NONE) {
if (entrance->GetConnectedRegionKey() != RR_NONE) {
RestoreConnections(entrance, target);
}
}
@@ -462,7 +463,7 @@ static bool ReplaceEntrance(Entrance* entrance, Entrance* target, std::vector<En
// Connect one random entrance from entrance pools to one random target in the respective target pool.
// Entrance chosen will have one of the allowed types.
// Target chosen will lead to one of the allowed regions.
static bool PlaceOneWayPriorityEntrance(std::string priorityName, std::list<AreaKey>& allowedRegions, std::list<EntranceType>& allowedTypes, std::vector<EntrancePair>& rollbacks, EntrancePools oneWayEntrancePools, EntrancePools oneWayTargetEntrancePools) {
static bool PlaceOneWayPriorityEntrance(std::string priorityName, std::list<RandomizerRegion>& allowedRegions, std::list<EntranceType>& allowedTypes, std::vector<EntrancePair>& rollbacks, EntrancePools oneWayEntrancePools, EntrancePools oneWayTargetEntrancePools) {
// Combine the entrances for allowed types in one list.
// Shuffle this list.
// Pick the first one not already set, not adult spawn, that has a valid target entrance.
@@ -482,20 +483,20 @@ static bool PlaceOneWayPriorityEntrance(std::string priorityName, std::list<Area
}
// Only allow Adult Spawn as sole Nocturne access if hints != mask.
// Otherwise, child access is required here (adult access assumed or guaranteed later).
if (entrance->GetParentRegionKey() == ADULT_SPAWN) {
if (entrance->GetParentRegionKey() == RR_ADULT_SPAWN) {
if (priorityName != "Nocturne" || Settings::GossipStoneHints.Is(HINTS_MASK_OF_TRUTH)) {
continue;
}
}
// If not shuffling dungeons, Nocturne requires adult access
if (!Settings::ShuffleDungeonEntrances && priorityName == "Nocturne") {
if (entrance->GetType() != EntranceType::WarpSong && entrance->GetParentRegionKey() != ADULT_SPAWN) {
if (entrance->GetType() != EntranceType::WarpSong && entrance->GetParentRegionKey() != RR_ADULT_SPAWN) {
continue;
}
}
for (Entrance* target : oneWayTargetEntrancePools[entrance->GetType()]) {
AreaKey targetRegionKey = target->GetConnectedRegionKey();
if (targetRegionKey != NONE && ElementInContainer(targetRegionKey, allowedRegions)) {
RandomizerRegion targetRegionKey = target->GetConnectedRegionKey();
if (targetRegionKey != RR_NONE && ElementInContainer(targetRegionKey, allowedRegions)) {
if (ReplaceEntrance(entrance, target, rollbacks)) {
// Return once the entrance has been replaced
return true;
@@ -514,7 +515,10 @@ static bool PlaceOneWayPriorityEntrance(std::string priorityName, std::list<Area
// Once the first entrance to Impas House has been placed, try to place the next one immediately to reduce chances of failure.
static bool PlaceOtherImpasHouseEntrance(std::vector<Entrance*> entrances, std::vector<Entrance*> targetEntrances, std::vector<EntrancePair>& rollbacks) {
// Get the other impas house entrance
auto otherImpaTargets = FilterFromPool(targetEntrances, [](const Entrance* target){return (target->GetConnectedRegionKey() == KAK_IMPAS_HOUSE || target->GetConnectedRegionKey() == KAK_IMPAS_HOUSE_BACK);});
auto otherImpaTargets = FilterFromPool(targetEntrances, [](const Entrance* target) {
return (target->GetConnectedRegionKey() == RR_KAK_IMPAS_HOUSE ||
target->GetConnectedRegionKey() == RR_KAK_IMPAS_HOUSE_BACK);
});
if (otherImpaTargets.empty()) {
return true;
}
@@ -522,11 +526,14 @@ static bool PlaceOtherImpasHouseEntrance(std::vector<Entrance*> entrances, std::
Entrance* otherImpaTarget = otherImpaTargets[0];
auto m = "Now Placing Other Impa Target: " + otherImpaTarget->GetName() + "\n";
SPDLOG_DEBUG(m);
AreaKey otherImpaRegion = otherImpaTarget->GetConnectedRegionKey() != KAK_IMPAS_HOUSE_BACK ? KAK_IMPAS_HOUSE_BACK : KAK_IMPAS_HOUSE;
RandomizerRegion otherImpaRegion = otherImpaTarget->GetConnectedRegionKey() != RR_KAK_IMPAS_HOUSE_BACK
? RR_KAK_IMPAS_HOUSE_BACK
: RR_KAK_IMPAS_HOUSE;
for (Entrance* entrance : entrances) {
// If the entrance is already connected or it doesn't have the same hint region as the already placed impas house entrance, then don't try to use it
if (entrance->GetConnectedRegionKey() != NONE || (GetHintRegionHintKey(otherImpaRegion) != GetHintRegionHintKey(entrance->GetParentRegionKey()))) {
continue;
if (entrance->GetConnectedRegionKey() != RR_NONE ||
(GetHintRegionHintKey(otherImpaRegion) != GetHintRegionHintKey(entrance->GetParentRegionKey()))) {
continue;
}
// If the placement succeeds, we return true
if (ReplaceEntrance(entrance, otherImpaTarget, rollbacks)) {
@@ -544,18 +551,18 @@ static bool ShuffleEntrances(std::vector<Entrance*>& entrances, std::vector<Entr
//place all entrances in the pool, validating after every placement
for (Entrance* entrance : entrances) {
if (entrance->GetConnectedRegionKey() != NONE) {
if (entrance->GetConnectedRegionKey() != RR_NONE) {
continue;
}
Shuffle(targetEntrances);
for (Entrance* target : targetEntrances) {
if (target->GetConnectedRegionKey() == NONE) {
if (target->GetConnectedRegionKey() == RR_NONE) {
continue;
}
// Store whether or not we're about to attempt placing an entrance to Impas House
bool attemptedImpasHousePlacement = (target->GetConnectedRegionKey() == KAK_IMPAS_HOUSE || target->GetConnectedRegionKey() == KAK_IMPAS_HOUSE_BACK);
bool attemptedImpasHousePlacement = (target->GetConnectedRegionKey() == RR_KAK_IMPAS_HOUSE || target->GetConnectedRegionKey() == RR_KAK_IMPAS_HOUSE_BACK);
if (ReplaceEntrance(entrance, target, rollbacks)) {
// If shuffle cows is enabled and the last entrance was one to Impas House,
@@ -569,7 +576,7 @@ static bool ShuffleEntrances(std::vector<Entrance*>& entrances, std::vector<Entr
}
}
if (entrance->GetConnectedRegionKey() == NONE) {
if (entrance->GetConnectedRegionKey() == RR_NONE) {
return false;
}
}
@@ -687,287 +694,294 @@ int ShuffleAllEntrances() {
curNumRandomizedEntrances = 0;
std::vector<EntranceInfoPair> entranceShuffleTable = {
//Parent Region Connected Region index blue warp
{{EntranceType::Dungeon, KF_OUTSIDE_DEKU_TREE, DEKU_TREE_ENTRYWAY, 0x0000},
{EntranceType::Dungeon, DEKU_TREE_ENTRYWAY, KF_OUTSIDE_DEKU_TREE, 0x0209, 0x0457}},
{{EntranceType::Dungeon, DEATH_MOUNTAIN_TRAIL, DODONGOS_CAVERN_ENTRYWAY, 0x0004},
{EntranceType::Dungeon, DODONGOS_CAVERN_ENTRYWAY, DEATH_MOUNTAIN_TRAIL, 0x0242, 0x047A}},
{{EntranceType::Dungeon, ZORAS_FOUNTAIN, JABU_JABUS_BELLY_ENTRYWAY, 0x0028},
{EntranceType::Dungeon, JABU_JABUS_BELLY_ENTRYWAY, ZORAS_FOUNTAIN, 0x0221, 0x010E}},
{{EntranceType::Dungeon, SACRED_FOREST_MEADOW, FOREST_TEMPLE_ENTRYWAY, 0x0169},
{EntranceType::Dungeon, FOREST_TEMPLE_ENTRYWAY, SACRED_FOREST_MEADOW, 0x0215, 0x0608}},
{{EntranceType::Dungeon, DMC_CENTRAL_LOCAL, FIRE_TEMPLE_ENTRYWAY, 0x0165},
{EntranceType::Dungeon, FIRE_TEMPLE_ENTRYWAY, DMC_CENTRAL_LOCAL, 0x024A, 0x0564}},
{{EntranceType::Dungeon, LAKE_HYLIA, WATER_TEMPLE_ENTRYWAY, 0x0010},
{EntranceType::Dungeon, WATER_TEMPLE_ENTRYWAY, LAKE_HYLIA, 0x021D, 0x060C}},
{{EntranceType::Dungeon, DESERT_COLOSSUS, SPIRIT_TEMPLE_ENTRYWAY, 0x0082},
{EntranceType::Dungeon, SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, 0x01E1, 0x0610}},
{{EntranceType::Dungeon, GRAVEYARD_WARP_PAD_REGION, SHADOW_TEMPLE_ENTRYWAY, 0x0037},
{EntranceType::Dungeon, SHADOW_TEMPLE_ENTRYWAY, GRAVEYARD_WARP_PAD_REGION, 0x0205, 0x0580}},
{{EntranceType::Dungeon, KAKARIKO_VILLAGE, BOTTOM_OF_THE_WELL_ENTRYWAY, 0x0098},
{EntranceType::Dungeon, BOTTOM_OF_THE_WELL_ENTRYWAY, KAKARIKO_VILLAGE, 0x02A6}},
{{EntranceType::Dungeon, ZORAS_FOUNTAIN, ICE_CAVERN_ENTRYWAY, 0x0088},
{EntranceType::Dungeon, ICE_CAVERN_ENTRYWAY, ZORAS_FOUNTAIN, 0x03D4}},
{{EntranceType::Dungeon, GERUDO_FORTRESS, GERUDO_TRAINING_GROUNDS_ENTRYWAY, 0x0008},
{EntranceType::Dungeon, GERUDO_TRAINING_GROUNDS_ENTRYWAY, GERUDO_FORTRESS, 0x03A8}},
{{EntranceType::GanonDungeon, GANONS_CASTLE_LEDGE, GANONS_CASTLE_ENTRYWAY, 0x0467},
{EntranceType::GanonDungeon, GANONS_CASTLE_ENTRYWAY, CASTLE_GROUNDS_FROM_GANONS_CASTLE, 0x023D}},
// Parent Region Connected Region index blue warp
{ { EntranceType::Dungeon, RR_KF_OUTSIDE_DEKU_TREE, RR_DEKU_TREE_ENTRYWAY, 0x0000 },
{ EntranceType::Dungeon, RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE, 0x0209, 0x0457 } },
{ { EntranceType::Dungeon, RR_DEATH_MOUNTAIN_TRAIL, RR_DODONGOS_CAVERN_ENTRYWAY, 0x0004 },
{ EntranceType::Dungeon, RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL, 0x0242, 0x047A } },
{ { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_JABU_JABUS_BELLY_ENTRYWAY, 0x0028 },
{ EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, 0x0221, 0x010E } },
{ { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, 0x0169 },
{ EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, 0x0215, 0x0608 } },
{ { EntranceType::Dungeon, RR_DMC_CENTRAL_LOCAL, RR_FIRE_TEMPLE_ENTRYWAY, 0x0165 },
{ EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, 0x024A, 0x0564 } },
{ { EntranceType::Dungeon, RR_LAKE_HYLIA, RR_WATER_TEMPLE_ENTRYWAY, 0x0010 },
{ EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA, 0x021D, 0x060C } },
{ { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, 0x0082 },
{ EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, 0x01E1, 0x0610 } },
{ { EntranceType::Dungeon, RR_GRAVEYARD_WARP_PAD_REGION, RR_SHADOW_TEMPLE_ENTRYWAY, 0x0037 },
{ EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, 0x0205, 0x0580 } },
{ { EntranceType::Dungeon, RR_KAKARIKO_VILLAGE, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, 0x0098 },
{ EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAKARIKO_VILLAGE, 0x02A6 } },
{ { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_ICE_CAVERN_ENTRYWAY, 0x0088 },
{ EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZORAS_FOUNTAIN, 0x03D4 } },
{ { EntranceType::Dungeon, RR_GERUDO_FORTRESS, RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, 0x0008 },
{ EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, RR_GERUDO_FORTRESS, 0x03A8 } },
{ { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, 0x0467 },
{ EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, 0x023D } },
{{EntranceType::Interior, KOKIRI_FOREST, KF_MIDOS_HOUSE, 0x0433},
{EntranceType::Interior, KF_MIDOS_HOUSE, KOKIRI_FOREST, 0x0443}},
{{EntranceType::Interior, KOKIRI_FOREST, KF_SARIAS_HOUSE, 0x0437},
{EntranceType::Interior, KF_SARIAS_HOUSE, KOKIRI_FOREST, 0x0447}},
{{EntranceType::Interior, KOKIRI_FOREST, KF_HOUSE_OF_TWINS, 0x009C},
{EntranceType::Interior, KF_HOUSE_OF_TWINS, KOKIRI_FOREST, 0x033C}},
{{EntranceType::Interior, KOKIRI_FOREST, KF_KNOW_IT_ALL_HOUSE, 0x00C9},
{EntranceType::Interior, KF_KNOW_IT_ALL_HOUSE, KOKIRI_FOREST, 0x026A}},
{{EntranceType::Interior, KOKIRI_FOREST, KF_KOKIRI_SHOP, 0x00C1},
{EntranceType::Interior, KF_KOKIRI_SHOP, KOKIRI_FOREST, 0x0266}},
{{EntranceType::Interior, LAKE_HYLIA, LH_LAB, 0x0043},
{EntranceType::Interior, LH_LAB, LAKE_HYLIA, 0x03CC}},
{{EntranceType::Interior, LH_FISHING_ISLAND, LH_FISHING_HOLE, 0x045F},
{EntranceType::Interior, LH_FISHING_HOLE, LH_FISHING_ISLAND, 0x0309}},
{{EntranceType::Interior, GV_FORTRESS_SIDE, GV_CARPENTER_TENT, 0x03A0},
{EntranceType::Interior, GV_CARPENTER_TENT, GV_FORTRESS_SIDE, 0x03D0}},
{{EntranceType::Interior, MARKET_ENTRANCE, MARKET_GUARD_HOUSE, 0x007E},
{EntranceType::Interior, MARKET_GUARD_HOUSE, MARKET_ENTRANCE, 0x026E}},
{{EntranceType::Interior, THE_MARKET, MARKET_MASK_SHOP, 0x0530},
{EntranceType::Interior, MARKET_MASK_SHOP, THE_MARKET, 0x01D1}},
{{EntranceType::Interior, THE_MARKET, MARKET_BOMBCHU_BOWLING, 0x0507},
{EntranceType::Interior, MARKET_BOMBCHU_BOWLING, THE_MARKET, 0x03BC}},
{{EntranceType::Interior, THE_MARKET, MARKET_POTION_SHOP, 0x0388},
{EntranceType::Interior, MARKET_POTION_SHOP, THE_MARKET, 0x02A2}},
{{EntranceType::Interior, THE_MARKET, MARKET_TREASURE_CHEST_GAME, 0x0063},
{EntranceType::Interior, MARKET_TREASURE_CHEST_GAME, THE_MARKET, 0x01D5}},
{{EntranceType::Interior, MARKET_BACK_ALLEY, MARKET_BOMBCHU_SHOP, 0x0528},
{EntranceType::Interior, MARKET_BOMBCHU_SHOP, MARKET_BACK_ALLEY, 0x03C0}},
{{EntranceType::Interior, MARKET_BACK_ALLEY, MARKET_MAN_IN_GREEN_HOUSE, 0x043B},
{EntranceType::Interior, MARKET_MAN_IN_GREEN_HOUSE, MARKET_BACK_ALLEY, 0x0067}},
{{EntranceType::Interior, KAKARIKO_VILLAGE, KAK_CARPENTER_BOSS_HOUSE, 0x02FD},
{EntranceType::Interior, KAK_CARPENTER_BOSS_HOUSE, KAKARIKO_VILLAGE, 0x0349}},
{{EntranceType::Interior, KAKARIKO_VILLAGE, KAK_HOUSE_OF_SKULLTULA, 0x0550},
{EntranceType::Interior, KAK_HOUSE_OF_SKULLTULA, KAKARIKO_VILLAGE, 0x04EE}},
{{EntranceType::Interior, KAKARIKO_VILLAGE, KAK_IMPAS_HOUSE, 0x039C},
{EntranceType::Interior, KAK_IMPAS_HOUSE, KAKARIKO_VILLAGE, 0x0345}},
{{EntranceType::Interior, KAK_IMPAS_LEDGE, KAK_IMPAS_HOUSE_BACK, 0x05C8},
{EntranceType::Interior, KAK_IMPAS_HOUSE_BACK, KAK_IMPAS_LEDGE, 0x05DC}},
{{EntranceType::Interior, KAK_BACKYARD, KAK_ODD_POTION_BUILDING, 0x0072},
{EntranceType::Interior, KAK_ODD_POTION_BUILDING, KAK_BACKYARD, 0x034D}},
{{EntranceType::Interior, THE_GRAVEYARD, GRAVEYARD_DAMPES_HOUSE, 0x030D},
{EntranceType::Interior, GRAVEYARD_DAMPES_HOUSE, THE_GRAVEYARD, 0x0355}},
{{EntranceType::Interior, GORON_CITY, GC_SHOP, 0x037C},
{EntranceType::Interior, GC_SHOP, GORON_CITY, 0x03FC}},
{{EntranceType::Interior, ZORAS_DOMAIN, ZD_SHOP, 0x0380},
{EntranceType::Interior, ZD_SHOP, ZORAS_DOMAIN, 0x03C4}},
{{EntranceType::Interior, LON_LON_RANCH, LLR_TALONS_HOUSE, 0x004F},
{EntranceType::Interior, LLR_TALONS_HOUSE, LON_LON_RANCH, 0x0378}},
{{EntranceType::Interior, LON_LON_RANCH, LLR_STABLES, 0x02F9},
{EntranceType::Interior, LLR_STABLES, LON_LON_RANCH, 0x042F}},
{{EntranceType::Interior, LON_LON_RANCH, LLR_TOWER, 0x05D0},
{EntranceType::Interior, LLR_TOWER, LON_LON_RANCH, 0x05D4}},
{{EntranceType::Interior, THE_MARKET, MARKET_BAZAAR, 0x052C},
{EntranceType::Interior, MARKET_BAZAAR, THE_MARKET, 0x03B8}},
{{EntranceType::Interior, THE_MARKET, MARKET_SHOOTING_GALLERY, 0x016D},
{EntranceType::Interior, MARKET_SHOOTING_GALLERY, THE_MARKET, 0x01CD}},
{{EntranceType::Interior, KAKARIKO_VILLAGE, KAK_BAZAAR, 0x00B7},
{EntranceType::Interior, KAK_BAZAAR, KAKARIKO_VILLAGE, 0x0201}},
{{EntranceType::Interior, KAKARIKO_VILLAGE, KAK_SHOOTING_GALLERY, 0x003B},
{EntranceType::Interior, KAK_SHOOTING_GALLERY, KAKARIKO_VILLAGE, 0x0463}},
{{EntranceType::Interior, DESERT_COLOSSUS, COLOSSUS_GREAT_FAIRY_FOUNTAIN, 0x0588},
{EntranceType::Interior, COLOSSUS_GREAT_FAIRY_FOUNTAIN, DESERT_COLOSSUS, 0x057C}},
{{EntranceType::Interior, HYRULE_CASTLE_GROUNDS, HC_GREAT_FAIRY_FOUNTAIN, 0x0578},
{EntranceType::Interior, HC_GREAT_FAIRY_FOUNTAIN, CASTLE_GROUNDS, 0x0340}},
{{EntranceType::Interior, GANONS_CASTLE_GROUNDS, OGC_GREAT_FAIRY_FOUNTAIN, 0x04C2},
{EntranceType::Interior, OGC_GREAT_FAIRY_FOUNTAIN, CASTLE_GROUNDS, 0x03E8}}, //0x3E8 is an unused entrance index repruposed to differentiate between the HC and OGC fairy fountain exits (normally they both use 0x340)
{{EntranceType::Interior, DMC_LOWER_NEARBY, DMC_GREAT_FAIRY_FOUNTAIN, 0x04BE},
{EntranceType::Interior, DMC_GREAT_FAIRY_FOUNTAIN, DMC_LOWER_LOCAL, 0x0482}},
{{EntranceType::Interior, DEATH_MOUNTAIN_SUMMIT, DMT_GREAT_FAIRY_FOUNTAIN, 0x0315},
{EntranceType::Interior, DMT_GREAT_FAIRY_FOUNTAIN, DEATH_MOUNTAIN_SUMMIT, 0x045B}},
{{EntranceType::Interior, ZORAS_FOUNTAIN, ZF_GREAT_FAIRY_FOUNTAIN, 0x0371},
{EntranceType::Interior, ZF_GREAT_FAIRY_FOUNTAIN, ZORAS_FOUNTAIN, 0x0394}},
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_MIDOS_HOUSE, 0x0433 },
{ EntranceType::Interior, RR_KF_MIDOS_HOUSE, RR_KOKIRI_FOREST, 0x0443 } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_SARIAS_HOUSE, 0x0437 },
{ EntranceType::Interior, RR_KF_SARIAS_HOUSE, RR_KOKIRI_FOREST, 0x0447 } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_HOUSE_OF_TWINS, 0x009C },
{ EntranceType::Interior, RR_KF_HOUSE_OF_TWINS, RR_KOKIRI_FOREST, 0x033C } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KNOW_IT_ALL_HOUSE, 0x00C9 },
{ EntranceType::Interior, RR_KF_KNOW_IT_ALL_HOUSE, RR_KOKIRI_FOREST, 0x026A } },
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KOKIRI_SHOP, 0x00C1 },
{ EntranceType::Interior, RR_KF_KOKIRI_SHOP, RR_KOKIRI_FOREST, 0x0266 } },
{ { EntranceType::Interior, RR_LAKE_HYLIA, RR_LH_LAB, 0x0043 },
{ EntranceType::Interior, RR_LH_LAB, RR_LAKE_HYLIA, 0x03CC } },
{ { EntranceType::Interior, RR_LH_FISHING_ISLAND, RR_LH_FISHING_HOLE, 0x045F },
{ EntranceType::Interior, RR_LH_FISHING_HOLE, RR_LH_FISHING_ISLAND, 0x0309 } },
{ { EntranceType::Interior, RR_GV_FORTRESS_SIDE, RR_GV_CARPENTER_TENT, 0x03A0 },
{ EntranceType::Interior, RR_GV_CARPENTER_TENT, RR_GV_FORTRESS_SIDE, 0x03D0 } },
{ { EntranceType::Interior, RR_MARKET_ENTRANCE, RR_MARKET_GUARD_HOUSE, 0x007E },
{ EntranceType::Interior, RR_MARKET_GUARD_HOUSE, RR_MARKET_ENTRANCE, 0x026E } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_MASK_SHOP, 0x0530 },
{ EntranceType::Interior, RR_MARKET_MASK_SHOP, RR_THE_MARKET, 0x01D1 } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BOMBCHU_BOWLING, 0x0507 },
{ EntranceType::Interior, RR_MARKET_BOMBCHU_BOWLING, RR_THE_MARKET, 0x03BC } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_POTION_SHOP, 0x0388 },
{ EntranceType::Interior, RR_MARKET_POTION_SHOP, RR_THE_MARKET, 0x02A2 } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_TREASURE_CHEST_GAME, 0x0063 },
{ EntranceType::Interior, RR_MARKET_TREASURE_CHEST_GAME, RR_THE_MARKET, 0x01D5 } },
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_BOMBCHU_SHOP, 0x0528 },
{ EntranceType::Interior, RR_MARKET_BOMBCHU_SHOP, RR_MARKET_BACK_ALLEY, 0x03C0 } },
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_MAN_IN_GREEN_HOUSE, 0x043B },
{ EntranceType::Interior, RR_MARKET_MAN_IN_GREEN_HOUSE, RR_MARKET_BACK_ALLEY, 0x0067 } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_CARPENTER_BOSS_HOUSE, 0x02FD },
{ EntranceType::Interior, RR_KAK_CARPENTER_BOSS_HOUSE, RR_KAKARIKO_VILLAGE, 0x0349 } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_HOUSE_OF_SKULLTULA, 0x0550 },
{ EntranceType::Interior, RR_KAK_HOUSE_OF_SKULLTULA, RR_KAKARIKO_VILLAGE, 0x04EE } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_IMPAS_HOUSE, 0x039C },
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE, RR_KAKARIKO_VILLAGE, 0x0345 } },
{ { EntranceType::Interior, RR_KAK_IMPAS_LEDGE, RR_KAK_IMPAS_HOUSE_BACK, 0x05C8 },
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE_BACK, RR_KAK_IMPAS_LEDGE, 0x05DC } },
{ { EntranceType::Interior, RR_KAK_BACKYARD, RR_KAK_ODD_POTION_BUILDING, 0x0072 },
{ EntranceType::Interior, RR_KAK_ODD_POTION_BUILDING, RR_KAK_BACKYARD, 0x034D } },
{ { EntranceType::Interior, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_HOUSE, 0x030D },
{ EntranceType::Interior, RR_GRAVEYARD_DAMPES_HOUSE, RR_THE_GRAVEYARD, 0x0355 } },
{ { EntranceType::Interior, RR_GORON_CITY, RR_GC_SHOP, 0x037C },
{ EntranceType::Interior, RR_GC_SHOP, RR_GORON_CITY, 0x03FC } },
{ { EntranceType::Interior, RR_ZORAS_DOMAIN, RR_ZD_SHOP, 0x0380 },
{ EntranceType::Interior, RR_ZD_SHOP, RR_ZORAS_DOMAIN, 0x03C4 } },
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TALONS_HOUSE, 0x004F },
{ EntranceType::Interior, RR_LLR_TALONS_HOUSE, RR_LON_LON_RANCH, 0x0378 } },
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_STABLES, 0x02F9 },
{ EntranceType::Interior, RR_LLR_STABLES, RR_LON_LON_RANCH, 0x042F } },
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TOWER, 0x05D0 },
{ EntranceType::Interior, RR_LLR_TOWER, RR_LON_LON_RANCH, 0x05D4 } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BAZAAR, 0x052C },
{ EntranceType::Interior, RR_MARKET_BAZAAR, RR_THE_MARKET, 0x03B8 } },
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_SHOOTING_GALLERY, 0x016D },
{ EntranceType::Interior, RR_MARKET_SHOOTING_GALLERY, RR_THE_MARKET, 0x01CD } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_BAZAAR, 0x00B7 },
{ EntranceType::Interior, RR_KAK_BAZAAR, RR_KAKARIKO_VILLAGE, 0x0201 } },
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_SHOOTING_GALLERY, 0x003B },
{ EntranceType::Interior, RR_KAK_SHOOTING_GALLERY, RR_KAKARIKO_VILLAGE, 0x0463 } },
{ { EntranceType::Interior, RR_DESERT_COLOSSUS, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, 0x0588 },
{ EntranceType::Interior, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, RR_DESERT_COLOSSUS, 0x057C } },
{ { EntranceType::Interior, RR_HYRULE_CASTLE_GROUNDS, RR_HC_GREAT_FAIRY_FOUNTAIN, 0x0578 },
{ EntranceType::Interior, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, 0x0340 } },
{ { EntranceType::Interior, RR_GANONS_CASTLE_GROUNDS, RR_OGC_GREAT_FAIRY_FOUNTAIN, 0x04C2 },
{ EntranceType::Interior, RR_OGC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS,
0x03E8 } }, // 0x3E8 is an unused entrance index repruposed to differentiate between the HC and OGC fairy
// fountain exits (normally they both use 0x340)
{ { EntranceType::Interior, RR_DMC_LOWER_NEARBY, RR_DMC_GREAT_FAIRY_FOUNTAIN, 0x04BE },
{ EntranceType::Interior, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_LOWER_LOCAL, 0x0482 } },
{ { EntranceType::Interior, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_GREAT_FAIRY_FOUNTAIN, 0x0315 },
{ EntranceType::Interior, RR_DMT_GREAT_FAIRY_FOUNTAIN, RR_DEATH_MOUNTAIN_SUMMIT, 0x045B } },
{ { EntranceType::Interior, RR_ZORAS_FOUNTAIN, RR_ZF_GREAT_FAIRY_FOUNTAIN, 0x0371 },
{ EntranceType::Interior, RR_ZF_GREAT_FAIRY_FOUNTAIN, RR_ZORAS_FOUNTAIN, 0x0394 } },
{{EntranceType::SpecialInterior, KOKIRI_FOREST, KF_LINKS_HOUSE, 0x0272},
{EntranceType::SpecialInterior, KF_LINKS_HOUSE, KOKIRI_FOREST, 0x0211}},
{{EntranceType::SpecialInterior, TOT_ENTRANCE, TEMPLE_OF_TIME, 0x0053},
{EntranceType::SpecialInterior, TEMPLE_OF_TIME, TOT_ENTRANCE, 0x0472}},
{{EntranceType::SpecialInterior, KAKARIKO_VILLAGE, KAK_WINDMILL, 0x0453},
{EntranceType::SpecialInterior, KAK_WINDMILL, KAKARIKO_VILLAGE, 0x0351}},
{{EntranceType::SpecialInterior, KAKARIKO_VILLAGE, KAK_POTION_SHOP_FRONT, 0x0384},
{EntranceType::SpecialInterior, KAK_POTION_SHOP_FRONT, KAKARIKO_VILLAGE, 0x044B}},
{{EntranceType::SpecialInterior, KAK_BACKYARD, KAK_POTION_SHOP_BACK, 0x03EC},
{EntranceType::SpecialInterior, KAK_POTION_SHOP_BACK, KAK_BACKYARD, 0x04FF}},
{ { EntranceType::SpecialInterior, RR_KOKIRI_FOREST, RR_KF_LINKS_HOUSE, 0x0272 },
{ EntranceType::SpecialInterior, RR_KF_LINKS_HOUSE, RR_KOKIRI_FOREST, 0x0211 } },
{ { EntranceType::SpecialInterior, RR_TOT_ENTRANCE, RR_TEMPLE_OF_TIME, 0x0053 },
{ EntranceType::SpecialInterior, RR_TEMPLE_OF_TIME, RR_TOT_ENTRANCE, 0x0472 } },
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_WINDMILL, 0x0453 },
{ EntranceType::SpecialInterior, RR_KAK_WINDMILL, RR_KAKARIKO_VILLAGE, 0x0351 } },
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_POTION_SHOP_FRONT, 0x0384 },
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_FRONT, RR_KAKARIKO_VILLAGE, 0x044B } },
{ { EntranceType::SpecialInterior, RR_KAK_BACKYARD, RR_KAK_POTION_SHOP_BACK, 0x03EC },
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_BACK, RR_KAK_BACKYARD, 0x04FF } },
// Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the
// grottoLoadTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
// Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the
// grottoReturnTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
{{EntranceType::GrottoGrave, DESERT_COLOSSUS, COLOSSUS_GROTTO, 0x0700},
{EntranceType::GrottoGrave, COLOSSUS_GROTTO, DESERT_COLOSSUS, 0x0800}},
{{EntranceType::GrottoGrave, LAKE_HYLIA, LH_GROTTO, 0x0701},
{EntranceType::GrottoGrave, LH_GROTTO, LAKE_HYLIA, 0x0801}},
{{EntranceType::GrottoGrave, ZORAS_RIVER, ZR_STORMS_GROTTO, 0x0702},
{EntranceType::GrottoGrave, ZR_STORMS_GROTTO, ZORAS_RIVER, 0x0802}},
{{EntranceType::GrottoGrave, ZORAS_RIVER, ZR_FAIRY_GROTTO, 0x0703},
{EntranceType::GrottoGrave, ZR_FAIRY_GROTTO, ZORAS_RIVER, 0x0803}},
{{EntranceType::GrottoGrave, ZORAS_RIVER, ZR_OPEN_GROTTO, 0x0704},
{EntranceType::GrottoGrave, ZR_OPEN_GROTTO, ZORAS_RIVER, 0x0804}},
{{EntranceType::GrottoGrave, DMC_LOWER_NEARBY, DMC_HAMMER_GROTTO, 0x0705},
{EntranceType::GrottoGrave, DMC_HAMMER_GROTTO, DMC_LOWER_LOCAL, 0x0805}},
{{EntranceType::GrottoGrave, DMC_UPPER_NEARBY, DMC_UPPER_GROTTO, 0x0706},
{EntranceType::GrottoGrave, DMC_UPPER_GROTTO, DMC_UPPER_LOCAL, 0x0806}},
{{EntranceType::GrottoGrave, GC_GROTTO_PLATFORM, GC_GROTTO, 0x0707},
{EntranceType::GrottoGrave, GC_GROTTO, GC_GROTTO_PLATFORM, 0x0807}},
{{EntranceType::GrottoGrave, DEATH_MOUNTAIN_TRAIL, DMT_STORMS_GROTTO, 0x0708},
{EntranceType::GrottoGrave, DMT_STORMS_GROTTO, DEATH_MOUNTAIN_TRAIL, 0x0808}},
{{EntranceType::GrottoGrave, DEATH_MOUNTAIN_SUMMIT, DMT_COW_GROTTO, 0x0709},
{EntranceType::GrottoGrave, DMT_COW_GROTTO, DEATH_MOUNTAIN_SUMMIT, 0x0809}},
{{EntranceType::GrottoGrave, KAK_BACKYARD, KAK_OPEN_GROTTO, 0x070A},
{EntranceType::GrottoGrave, KAK_OPEN_GROTTO, KAK_BACKYARD, 0x080A}},
{{EntranceType::GrottoGrave, KAKARIKO_VILLAGE, KAK_REDEAD_GROTTO, 0x070B},
{EntranceType::GrottoGrave, KAK_REDEAD_GROTTO, KAKARIKO_VILLAGE, 0x080B}},
{{EntranceType::GrottoGrave, HYRULE_CASTLE_GROUNDS, HC_STORMS_GROTTO, 0x070C},
{EntranceType::GrottoGrave, HC_STORMS_GROTTO, CASTLE_GROUNDS, 0x080C}},
{{EntranceType::GrottoGrave, HYRULE_FIELD, HF_TEKTITE_GROTTO, 0x070D},
{EntranceType::GrottoGrave, HF_TEKTITE_GROTTO, HYRULE_FIELD, 0x080D}},
{{EntranceType::GrottoGrave, HYRULE_FIELD, HF_NEAR_KAK_GROTTO, 0x070E},
{EntranceType::GrottoGrave, HF_NEAR_KAK_GROTTO, HYRULE_FIELD, 0x080E}},
{{EntranceType::GrottoGrave, HYRULE_FIELD, HF_FAIRY_GROTTO, 0x070F},
{EntranceType::GrottoGrave, HF_FAIRY_GROTTO, HYRULE_FIELD, 0x080F}},
{{EntranceType::GrottoGrave, HYRULE_FIELD, HF_NEAR_MARKET_GROTTO, 0x0710},
{EntranceType::GrottoGrave, HF_NEAR_MARKET_GROTTO, HYRULE_FIELD, 0x0810}},
{{EntranceType::GrottoGrave, HYRULE_FIELD, HF_COW_GROTTO, 0x0711},
{EntranceType::GrottoGrave, HF_COW_GROTTO, HYRULE_FIELD, 0x0811}},
{{EntranceType::GrottoGrave, HYRULE_FIELD, HF_INSIDE_FENCE_GROTTO, 0x0712},
{EntranceType::GrottoGrave, HF_INSIDE_FENCE_GROTTO, HYRULE_FIELD, 0x0812}},
{{EntranceType::GrottoGrave, HYRULE_FIELD, HF_OPEN_GROTTO, 0x0713},
{EntranceType::GrottoGrave, HF_OPEN_GROTTO, HYRULE_FIELD, 0x0813}},
{{EntranceType::GrottoGrave, HYRULE_FIELD, HF_SOUTHEAST_GROTTO, 0x0714},
{EntranceType::GrottoGrave, HF_SOUTHEAST_GROTTO, HYRULE_FIELD, 0x0814}},
{{EntranceType::GrottoGrave, LON_LON_RANCH, LLR_GROTTO, 0x0715},
{EntranceType::GrottoGrave, LLR_GROTTO, LON_LON_RANCH, 0x0815}},
{{EntranceType::GrottoGrave, SFM_ENTRYWAY, SFM_WOLFOS_GROTTO, 0x0716},
{EntranceType::GrottoGrave, SFM_WOLFOS_GROTTO, SFM_ENTRYWAY, 0x0816}},
{{EntranceType::GrottoGrave, SACRED_FOREST_MEADOW, SFM_STORMS_GROTTO, 0x0717},
{EntranceType::GrottoGrave, SFM_STORMS_GROTTO, SACRED_FOREST_MEADOW, 0x0817}},
{{EntranceType::GrottoGrave, SACRED_FOREST_MEADOW, SFM_FAIRY_GROTTO, 0x0718},
{EntranceType::GrottoGrave, SFM_FAIRY_GROTTO, SACRED_FOREST_MEADOW, 0x0818}},
{{EntranceType::GrottoGrave, LW_BEYOND_MIDO, LW_SCRUBS_GROTTO, 0x0719},
{EntranceType::GrottoGrave, LW_SCRUBS_GROTTO, LW_BEYOND_MIDO, 0x0819}},
{{EntranceType::GrottoGrave, THE_LOST_WOODS, LW_NEAR_SHORTCUTS_GROTTO, 0x071A},
{EntranceType::GrottoGrave, LW_NEAR_SHORTCUTS_GROTTO, THE_LOST_WOODS, 0x081A}},
{{EntranceType::GrottoGrave, KOKIRI_FOREST, KF_STORMS_GROTTO, 0x071B},
{EntranceType::GrottoGrave, KF_STORMS_GROTTO, KOKIRI_FOREST, 0x081B}},
{{EntranceType::GrottoGrave, ZORAS_DOMAIN, ZD_STORMS_GROTTO, 0x071C},
{EntranceType::GrottoGrave, ZD_STORMS_GROTTO, ZORAS_DOMAIN, 0x081C}},
{{EntranceType::GrottoGrave, GERUDO_FORTRESS, GF_STORMS_GROTTO, 0x071D},
{EntranceType::GrottoGrave, GF_STORMS_GROTTO, GERUDO_FORTRESS, 0x081D}},
{{EntranceType::GrottoGrave, GV_FORTRESS_SIDE, GV_STORMS_GROTTO, 0x071E},
{EntranceType::GrottoGrave, GV_STORMS_GROTTO, GV_FORTRESS_SIDE, 0x081E}},
{{EntranceType::GrottoGrave, GV_GROTTO_LEDGE, GV_OCTOROK_GROTTO, 0x071F},
{EntranceType::GrottoGrave, GV_OCTOROK_GROTTO, GV_GROTTO_LEDGE, 0x081F}},
{{EntranceType::GrottoGrave, LW_BEYOND_MIDO, DEKU_THEATER, 0x0720},
{EntranceType::GrottoGrave, DEKU_THEATER, LW_BEYOND_MIDO, 0x0820}},
// Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the
// grottoLoadTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
// Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the
// grottoReturnTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
{ { EntranceType::GrottoGrave, RR_DESERT_COLOSSUS, RR_COLOSSUS_GROTTO, 0x0700 },
{ EntranceType::GrottoGrave, RR_COLOSSUS_GROTTO, RR_DESERT_COLOSSUS, 0x0800 } },
{ { EntranceType::GrottoGrave, RR_LAKE_HYLIA, RR_LH_GROTTO, 0x0701 },
{ EntranceType::GrottoGrave, RR_LH_GROTTO, RR_LAKE_HYLIA, 0x0801 } },
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_STORMS_GROTTO, 0x0702 },
{ EntranceType::GrottoGrave, RR_ZR_STORMS_GROTTO, RR_ZORAS_RIVER, 0x0802 } },
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_FAIRY_GROTTO, 0x0703 },
{ EntranceType::GrottoGrave, RR_ZR_FAIRY_GROTTO, RR_ZORAS_RIVER, 0x0803 } },
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_OPEN_GROTTO, 0x0704 },
{ EntranceType::GrottoGrave, RR_ZR_OPEN_GROTTO, RR_ZORAS_RIVER, 0x0804 } },
{ { EntranceType::GrottoGrave, RR_DMC_LOWER_NEARBY, RR_DMC_HAMMER_GROTTO, 0x0705 },
{ EntranceType::GrottoGrave, RR_DMC_HAMMER_GROTTO, RR_DMC_LOWER_LOCAL, 0x0805 } },
{ { EntranceType::GrottoGrave, RR_DMC_UPPER_NEARBY, RR_DMC_UPPER_GROTTO, 0x0706 },
{ EntranceType::GrottoGrave, RR_DMC_UPPER_GROTTO, RR_DMC_UPPER_LOCAL, 0x0806 } },
{ { EntranceType::GrottoGrave, RR_GC_GROTTO_PLATFORM, RR_GC_GROTTO, 0x0707 },
{ EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, 0x0807 } },
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, 0x0708 },
{ EntranceType::GrottoGrave, RR_DMT_STORMS_GROTTO, RR_DEATH_MOUNTAIN_TRAIL, 0x0808 } },
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_COW_GROTTO, 0x0709 },
{ EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_SUMMIT, 0x0809 } },
{ { EntranceType::GrottoGrave, RR_KAK_BACKYARD, RR_KAK_OPEN_GROTTO, 0x070A },
{ EntranceType::GrottoGrave, RR_KAK_OPEN_GROTTO, RR_KAK_BACKYARD, 0x080A } },
{ { EntranceType::GrottoGrave, RR_KAKARIKO_VILLAGE, RR_KAK_REDEAD_GROTTO, 0x070B },
{ EntranceType::GrottoGrave, RR_KAK_REDEAD_GROTTO, RR_KAKARIKO_VILLAGE, 0x080B } },
{ { EntranceType::GrottoGrave, RR_HYRULE_CASTLE_GROUNDS, RR_HC_STORMS_GROTTO, 0x070C },
{ EntranceType::GrottoGrave, RR_HC_STORMS_GROTTO, RR_CASTLE_GROUNDS, 0x080C } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_TEKTITE_GROTTO, 0x070D },
{ EntranceType::GrottoGrave, RR_HF_TEKTITE_GROTTO, RR_HYRULE_FIELD, 0x080D } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_KAK_GROTTO, 0x070E },
{ EntranceType::GrottoGrave, RR_HF_NEAR_KAK_GROTTO, RR_HYRULE_FIELD, 0x080E } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_FAIRY_GROTTO, 0x070F },
{ EntranceType::GrottoGrave, RR_HF_FAIRY_GROTTO, RR_HYRULE_FIELD, 0x080F } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_MARKET_GROTTO, 0x0710 },
{ EntranceType::GrottoGrave, RR_HF_NEAR_MARKET_GROTTO, RR_HYRULE_FIELD, 0x0810 } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_COW_GROTTO, 0x0711 },
{ EntranceType::GrottoGrave, RR_HF_COW_GROTTO, RR_HYRULE_FIELD, 0x0811 } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_INSIDE_FENCE_GROTTO, 0x0712 },
{ EntranceType::GrottoGrave, RR_HF_INSIDE_FENCE_GROTTO, RR_HYRULE_FIELD, 0x0812 } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_OPEN_GROTTO, 0x0713 },
{ EntranceType::GrottoGrave, RR_HF_OPEN_GROTTO, RR_HYRULE_FIELD, 0x0813 } },
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_SOUTHEAST_GROTTO, 0x0714 },
{ EntranceType::GrottoGrave, RR_HF_SOUTHEAST_GROTTO, RR_HYRULE_FIELD, 0x0814 } },
{ { EntranceType::GrottoGrave, RR_LON_LON_RANCH, RR_LLR_GROTTO, 0x0715 },
{ EntranceType::GrottoGrave, RR_LLR_GROTTO, RR_LON_LON_RANCH, 0x0815 } },
{ { EntranceType::GrottoGrave, RR_SFM_ENTRYWAY, RR_SFM_WOLFOS_GROTTO, 0x0716 },
{ EntranceType::GrottoGrave, RR_SFM_WOLFOS_GROTTO, RR_SFM_ENTRYWAY, 0x0816 } },
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_STORMS_GROTTO, 0x0717 },
{ EntranceType::GrottoGrave, RR_SFM_STORMS_GROTTO, RR_SACRED_FOREST_MEADOW, 0x0817 } },
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_FAIRY_GROTTO, 0x0718 },
{ EntranceType::GrottoGrave, RR_SFM_FAIRY_GROTTO, RR_SACRED_FOREST_MEADOW, 0x0818 } },
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_LW_SCRUBS_GROTTO, 0x0719 },
{ EntranceType::GrottoGrave, RR_LW_SCRUBS_GROTTO, RR_LW_BEYOND_MIDO, 0x0819 } },
{ { EntranceType::GrottoGrave, RR_THE_LOST_WOODS, RR_LW_NEAR_SHORTCUTS_GROTTO, 0x071A },
{ EntranceType::GrottoGrave, RR_LW_NEAR_SHORTCUTS_GROTTO, RR_THE_LOST_WOODS, 0x081A } },
{ { EntranceType::GrottoGrave, RR_KOKIRI_FOREST, RR_KF_STORMS_GROTTO, 0x071B },
{ EntranceType::GrottoGrave, RR_KF_STORMS_GROTTO, RR_KOKIRI_FOREST, 0x081B } },
{ { EntranceType::GrottoGrave, RR_ZORAS_DOMAIN, RR_ZD_STORMS_GROTTO, 0x071C },
{ EntranceType::GrottoGrave, RR_ZD_STORMS_GROTTO, RR_ZORAS_DOMAIN, 0x081C } },
{ { EntranceType::GrottoGrave, RR_GERUDO_FORTRESS, RR_GF_STORMS_GROTTO, 0x071D },
{ EntranceType::GrottoGrave, RR_GF_STORMS_GROTTO, RR_GERUDO_FORTRESS, 0x081D } },
{ { EntranceType::GrottoGrave, RR_GV_FORTRESS_SIDE, RR_GV_STORMS_GROTTO, 0x071E },
{ EntranceType::GrottoGrave, RR_GV_STORMS_GROTTO, RR_GV_FORTRESS_SIDE, 0x081E } },
{ { EntranceType::GrottoGrave, RR_GV_GROTTO_LEDGE, RR_GV_OCTOROK_GROTTO, 0x071F },
{ EntranceType::GrottoGrave, RR_GV_OCTOROK_GROTTO, RR_GV_GROTTO_LEDGE, 0x081F } },
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_DEKU_THEATER, 0x0720 },
{ EntranceType::GrottoGrave, RR_DEKU_THEATER, RR_LW_BEYOND_MIDO, 0x0820 } },
// Graves have their own specified entrance indices
{{EntranceType::GrottoGrave, THE_GRAVEYARD, GRAVEYARD_SHIELD_GRAVE, 0x004B},
{EntranceType::GrottoGrave, GRAVEYARD_SHIELD_GRAVE, THE_GRAVEYARD, 0x035D}},
{{EntranceType::GrottoGrave, THE_GRAVEYARD, GRAVEYARD_HEART_PIECE_GRAVE, 0x031C},
{EntranceType::GrottoGrave, GRAVEYARD_HEART_PIECE_GRAVE, THE_GRAVEYARD, 0x0361}},
{{EntranceType::GrottoGrave, THE_GRAVEYARD, GRAVEYARD_COMPOSERS_GRAVE, 0x002D},
{EntranceType::GrottoGrave, GRAVEYARD_COMPOSERS_GRAVE, THE_GRAVEYARD, 0x050B}},
{{EntranceType::GrottoGrave, THE_GRAVEYARD, GRAVEYARD_DAMPES_GRAVE, 0x044F},
{EntranceType::GrottoGrave, GRAVEYARD_DAMPES_GRAVE, THE_GRAVEYARD, 0x0359}},
// Graves have their own specified entrance indices
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_SHIELD_GRAVE, 0x004B },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_SHIELD_GRAVE, RR_THE_GRAVEYARD, 0x035D } },
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_HEART_PIECE_GRAVE, 0x031C },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_THE_GRAVEYARD, 0x0361 } },
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_COMPOSERS_GRAVE, 0x002D },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_COMPOSERS_GRAVE, RR_THE_GRAVEYARD, 0x050B } },
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_GRAVE, 0x044F },
{ EntranceType::GrottoGrave, RR_GRAVEYARD_DAMPES_GRAVE, RR_THE_GRAVEYARD, 0x0359 } },
{{EntranceType::Overworld, KOKIRI_FOREST, LW_BRIDGE_FROM_FOREST, 0x05E0},
{EntranceType::Overworld, LW_BRIDGE, KOKIRI_FOREST, 0x020D}},
{{EntranceType::Overworld, KOKIRI_FOREST, THE_LOST_WOODS, 0x011E},
{EntranceType::Overworld, LW_FOREST_EXIT, KOKIRI_FOREST, 0x0286}},
{{EntranceType::Overworld, THE_LOST_WOODS, GC_WOODS_WARP, 0x04E2},
{EntranceType::Overworld, GC_WOODS_WARP, THE_LOST_WOODS, 0x04D6}},
{{EntranceType::Overworld, THE_LOST_WOODS, ZORAS_RIVER, 0x01DD},
{EntranceType::Overworld, ZORAS_RIVER, THE_LOST_WOODS, 0x04DA}},
{{EntranceType::Overworld, LW_BEYOND_MIDO, SFM_ENTRYWAY, 0x00FC},
{EntranceType::Overworld, SFM_ENTRYWAY, LW_BEYOND_MIDO, 0x01A9}},
{{EntranceType::Overworld, LW_BRIDGE, HYRULE_FIELD, 0x0185},
{EntranceType::Overworld, HYRULE_FIELD, LW_BRIDGE, 0x04DE}},
{{EntranceType::Overworld, HYRULE_FIELD, LAKE_HYLIA, 0x0102},
{EntranceType::Overworld, LAKE_HYLIA, HYRULE_FIELD, 0x0189}},
{{EntranceType::Overworld, HYRULE_FIELD, GERUDO_VALLEY, 0x0117},
{EntranceType::Overworld, GERUDO_VALLEY, HYRULE_FIELD, 0x018D}},
{{EntranceType::Overworld, HYRULE_FIELD, MARKET_ENTRANCE, 0x0276},
{EntranceType::Overworld, MARKET_ENTRANCE, HYRULE_FIELD, 0x01FD}},
{{EntranceType::Overworld, HYRULE_FIELD, KAKARIKO_VILLAGE, 0x00DB},
{EntranceType::Overworld, KAKARIKO_VILLAGE, HYRULE_FIELD, 0x017D}},
{{EntranceType::Overworld, HYRULE_FIELD, ZR_FRONT, 0x00EA},
{EntranceType::Overworld, ZR_FRONT, HYRULE_FIELD, 0x0181}},
{{EntranceType::Overworld, HYRULE_FIELD, LON_LON_RANCH, 0x0157},
{EntranceType::Overworld, LON_LON_RANCH, HYRULE_FIELD, 0x01F9}},
{{EntranceType::Overworld, LAKE_HYLIA, ZORAS_DOMAIN, 0x0328},
{EntranceType::Overworld, ZORAS_DOMAIN, LAKE_HYLIA, 0x0560}},
{{EntranceType::Overworld, GV_FORTRESS_SIDE, GERUDO_FORTRESS, 0x0129},
{EntranceType::Overworld, GERUDO_FORTRESS, GV_FORTRESS_SIDE, 0x022D}},
{{EntranceType::Overworld, GF_OUTSIDE_GATE, WASTELAND_NEAR_FORTRESS, 0x0130},
{EntranceType::Overworld, WASTELAND_NEAR_FORTRESS, GF_OUTSIDE_GATE, 0x03AC}},
{{EntranceType::Overworld, WASTELAND_NEAR_COLOSSUS, DESERT_COLOSSUS, 0x0123},
{EntranceType::Overworld, DESERT_COLOSSUS, WASTELAND_NEAR_COLOSSUS, 0x0365}},
{{EntranceType::Overworld, MARKET_ENTRANCE, THE_MARKET, 0x00B1},
{EntranceType::Overworld, THE_MARKET, MARKET_ENTRANCE, 0x0033}},
{{EntranceType::Overworld, THE_MARKET, CASTLE_GROUNDS, 0x0138},
{EntranceType::Overworld, CASTLE_GROUNDS, THE_MARKET, 0x025A}},
{{EntranceType::Overworld, THE_MARKET, TOT_ENTRANCE, 0x0171},
{EntranceType::Overworld, TOT_ENTRANCE, THE_MARKET, 0x025E}},
{{EntranceType::Overworld, KAKARIKO_VILLAGE, THE_GRAVEYARD, 0x00E4},
{EntranceType::Overworld, THE_GRAVEYARD, KAKARIKO_VILLAGE, 0x0195}},
{{EntranceType::Overworld, KAK_BEHIND_GATE, DEATH_MOUNTAIN_TRAIL, 0x013D},
{EntranceType::Overworld, DEATH_MOUNTAIN_TRAIL, KAK_BEHIND_GATE, 0x0191}},
{{EntranceType::Overworld, DEATH_MOUNTAIN_TRAIL, GORON_CITY, 0x014D},
{EntranceType::Overworld, GORON_CITY, DEATH_MOUNTAIN_TRAIL, 0x01B9}},
{{EntranceType::Overworld, GC_DARUNIAS_CHAMBER, DMC_LOWER_LOCAL, 0x0246},
{EntranceType::Overworld, DMC_LOWER_NEARBY, GC_DARUNIAS_CHAMBER, 0x01C1}},
{{EntranceType::Overworld, DEATH_MOUNTAIN_SUMMIT, DMC_UPPER_LOCAL, 0x0147},
{EntranceType::Overworld, DMC_UPPER_NEARBY, DEATH_MOUNTAIN_SUMMIT, 0x01BD}},
{{EntranceType::Overworld, ZR_BEHIND_WATERFALL, ZORAS_DOMAIN, 0x0108},
{EntranceType::Overworld, ZORAS_DOMAIN, ZR_BEHIND_WATERFALL, 0x019D}},
{{EntranceType::Overworld, ZD_BEHIND_KING_ZORA, ZORAS_FOUNTAIN, 0x0225},
{EntranceType::Overworld, ZORAS_FOUNTAIN, ZD_BEHIND_KING_ZORA, 0x01A1}},
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_LW_BRIDGE_FROM_FOREST, 0x05E0 },
{ EntranceType::Overworld, RR_LW_BRIDGE, RR_KOKIRI_FOREST, 0x020D } },
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_THE_LOST_WOODS, 0x011E },
{ EntranceType::Overworld, RR_LW_FOREST_EXIT, RR_KOKIRI_FOREST, 0x0286 } },
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_GC_WOODS_WARP, 0x04E2 },
{ EntranceType::Overworld, RR_GC_WOODS_WARP, RR_THE_LOST_WOODS, 0x04D6 } },
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_ZORAS_RIVER, 0x01DD },
{ EntranceType::Overworld, RR_ZORAS_RIVER, RR_THE_LOST_WOODS, 0x04DA } },
{ { EntranceType::Overworld, RR_LW_BEYOND_MIDO, RR_SFM_ENTRYWAY, 0x00FC },
{ EntranceType::Overworld, RR_SFM_ENTRYWAY, RR_LW_BEYOND_MIDO, 0x01A9 } },
{ { EntranceType::Overworld, RR_LW_BRIDGE, RR_HYRULE_FIELD, 0x0185 },
{ EntranceType::Overworld, RR_HYRULE_FIELD, RR_LW_BRIDGE, 0x04DE } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LAKE_HYLIA, 0x0102 },
{ EntranceType::Overworld, RR_LAKE_HYLIA, RR_HYRULE_FIELD, 0x0189 } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_GERUDO_VALLEY, 0x0117 },
{ EntranceType::Overworld, RR_GERUDO_VALLEY, RR_HYRULE_FIELD, 0x018D } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_MARKET_ENTRANCE, 0x0276 },
{ EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_HYRULE_FIELD, 0x01FD } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_KAKARIKO_VILLAGE, 0x00DB },
{ EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_HYRULE_FIELD, 0x017D } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_ZR_FRONT, 0x00EA },
{ EntranceType::Overworld, RR_ZR_FRONT, RR_HYRULE_FIELD, 0x0181 } },
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LON_LON_RANCH, 0x0157 },
{ EntranceType::Overworld, RR_LON_LON_RANCH, RR_HYRULE_FIELD, 0x01F9 } },
{ { EntranceType::Overworld, RR_LAKE_HYLIA, RR_ZORAS_DOMAIN, 0x0328 },
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_LAKE_HYLIA, 0x0560 } },
{ { EntranceType::Overworld, RR_GV_FORTRESS_SIDE, RR_GERUDO_FORTRESS, 0x0129 },
{ EntranceType::Overworld, RR_GERUDO_FORTRESS, RR_GV_FORTRESS_SIDE, 0x022D } },
{ { EntranceType::Overworld, RR_GF_OUTSIDE_GATE, RR_WASTELAND_NEAR_FORTRESS, 0x0130 },
{ EntranceType::Overworld, RR_WASTELAND_NEAR_FORTRESS, RR_GF_OUTSIDE_GATE, 0x03AC } },
{ { EntranceType::Overworld, RR_WASTELAND_NEAR_COLOSSUS, RR_DESERT_COLOSSUS, 0x0123 },
{ EntranceType::Overworld, RR_DESERT_COLOSSUS, RR_WASTELAND_NEAR_COLOSSUS, 0x0365 } },
{ { EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_THE_MARKET, 0x00B1 },
{ EntranceType::Overworld, RR_THE_MARKET, RR_MARKET_ENTRANCE, 0x0033 } },
{ { EntranceType::Overworld, RR_THE_MARKET, RR_CASTLE_GROUNDS, 0x0138 },
{ EntranceType::Overworld, RR_CASTLE_GROUNDS, RR_THE_MARKET, 0x025A } },
{ { EntranceType::Overworld, RR_THE_MARKET, RR_TOT_ENTRANCE, 0x0171 },
{ EntranceType::Overworld, RR_TOT_ENTRANCE, RR_THE_MARKET, 0x025E } },
{ { EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_THE_GRAVEYARD, 0x00E4 },
{ EntranceType::Overworld, RR_THE_GRAVEYARD, RR_KAKARIKO_VILLAGE, 0x0195 } },
{ { EntranceType::Overworld, RR_KAK_BEHIND_GATE, RR_DEATH_MOUNTAIN_TRAIL, 0x013D },
{ EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_KAK_BEHIND_GATE, 0x0191 } },
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_GORON_CITY, 0x014D },
{ EntranceType::Overworld, RR_GORON_CITY, RR_DEATH_MOUNTAIN_TRAIL, 0x01B9 } },
{ { EntranceType::Overworld, RR_GC_DARUNIAS_CHAMBER, RR_DMC_LOWER_LOCAL, 0x0246 },
{ EntranceType::Overworld, RR_DMC_LOWER_NEARBY, RR_GC_DARUNIAS_CHAMBER, 0x01C1 } },
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMC_UPPER_LOCAL, 0x0147 },
{ EntranceType::Overworld, RR_DMC_UPPER_NEARBY, RR_DEATH_MOUNTAIN_SUMMIT, 0x01BD } },
{ { EntranceType::Overworld, RR_ZR_BEHIND_WATERFALL, RR_ZORAS_DOMAIN, 0x0108 },
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_ZR_BEHIND_WATERFALL, 0x019D } },
{ { EntranceType::Overworld, RR_ZD_BEHIND_KING_ZORA, RR_ZORAS_FOUNTAIN, 0x0225 },
{ EntranceType::Overworld, RR_ZORAS_FOUNTAIN, RR_ZD_BEHIND_KING_ZORA, 0x01A1 } },
{{EntranceType::Overworld, GV_LOWER_STREAM, LAKE_HYLIA, 0x0219}, NO_RETURN_ENTRANCE},
{ { EntranceType::Overworld, RR_GV_LOWER_STREAM, RR_LAKE_HYLIA, 0x0219 }, NO_RETURN_ENTRANCE },
{{EntranceType::OwlDrop, LH_OWL_FLIGHT, HYRULE_FIELD, 0x027E}, NO_RETURN_ENTRANCE},
{{EntranceType::OwlDrop, DMT_OWL_FLIGHT, KAK_IMPAS_ROOFTOP, 0x0554}, NO_RETURN_ENTRANCE},
{ { EntranceType::OwlDrop, RR_LH_OWL_FLIGHT, RR_HYRULE_FIELD, 0x027E }, NO_RETURN_ENTRANCE },
{ { EntranceType::OwlDrop, RR_DMT_OWL_FLIGHT, RR_KAK_IMPAS_ROOFTOP, 0x0554 }, NO_RETURN_ENTRANCE },
{{EntranceType::Spawn, CHILD_SPAWN, KF_LINKS_HOUSE, 0x00BB}, NO_RETURN_ENTRANCE},
{{EntranceType::Spawn, ADULT_SPAWN, TEMPLE_OF_TIME, 0x0282}, NO_RETURN_ENTRANCE}, // 0x282 is an unused entrance index repurposed to differentiate between
// Adult Spawn and prelude of light (normally they both use 0x5F4)
{{EntranceType::WarpSong, MINUET_OF_FOREST_WARP, SACRED_FOREST_MEADOW, 0x0600}, NO_RETURN_ENTRANCE},
{{EntranceType::WarpSong, BOLERO_OF_FIRE_WARP, DMC_CENTRAL_LOCAL, 0x04F6}, NO_RETURN_ENTRANCE},
{{EntranceType::WarpSong, SERENADE_OF_WATER_WARP, LAKE_HYLIA, 0x0604}, NO_RETURN_ENTRANCE},
{{EntranceType::WarpSong, REQUIEM_OF_SPIRIT_WARP, DESERT_COLOSSUS, 0x01F1}, NO_RETURN_ENTRANCE},
{{EntranceType::WarpSong, NOCTURNE_OF_SHADOW_WARP, GRAVEYARD_WARP_PAD_REGION, 0x0568}, NO_RETURN_ENTRANCE},
{{EntranceType::WarpSong, PRELUDE_OF_LIGHT_WARP, TEMPLE_OF_TIME, 0x05F4}, NO_RETURN_ENTRANCE},
{ { EntranceType::Spawn, RR_CHILD_SPAWN, RR_KF_LINKS_HOUSE, 0x00BB }, NO_RETURN_ENTRANCE },
{ { EntranceType::Spawn, RR_ADULT_SPAWN, RR_TEMPLE_OF_TIME, 0x0282 },
NO_RETURN_ENTRANCE }, // 0x282 is an unused entrance index repurposed to differentiate between
// Adult Spawn and prelude of light (normally they both use 0x5F4)
{ { EntranceType::WarpSong, RR_MINUET_OF_FOREST_WARP, RR_SACRED_FOREST_MEADOW, 0x0600 }, NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_BOLERO_OF_FIRE_WARP, RR_DMC_CENTRAL_LOCAL, 0x04F6 }, NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_SERENADE_OF_WATER_WARP, RR_LAKE_HYLIA, 0x0604 }, NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_REQUIEM_OF_SPIRIT_WARP, RR_DESERT_COLOSSUS, 0x01F1 }, NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_NOCTURNE_OF_SHADOW_WARP, RR_GRAVEYARD_WARP_PAD_REGION, 0x0568 },
NO_RETURN_ENTRANCE },
{ { EntranceType::WarpSong, RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME, 0x05F4 }, NO_RETURN_ENTRANCE },
{{EntranceType::ChildBoss, DEKU_TREE_BOSS_ENTRYWAY, DEKU_TREE_BOSS_ROOM, 0x040F},
{EntranceType::ChildBoss, DEKU_TREE_BOSS_ROOM, DEKU_TREE_BOSS_ENTRYWAY, 0x0252, 0x0457}},
{{EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ENTRYWAY, DODONGOS_CAVERN_BOSS_ROOM, 0x040B},
{EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ROOM, DODONGOS_CAVERN_BOSS_ENTRYWAY, 0x00C5, 0x047A}},
{{EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ENTRYWAY, JABU_JABUS_BELLY_BOSS_ROOM, 0x0301},
{EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ROOM, JABU_JABUS_BELLY_BOSS_ENTRYWAY, 0x0407, 0x010E}},
{{EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ENTRYWAY, FOREST_TEMPLE_BOSS_ROOM, 0x000C},
{EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ROOM, FOREST_TEMPLE_BOSS_ENTRYWAY, 0x024E, 0x0608}},
{{EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ENTRYWAY, FIRE_TEMPLE_BOSS_ROOM, 0x0305},
{EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_BOSS_ENTRYWAY, 0x0175, 0x0564}},
{{EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ENTRYWAY, WATER_TEMPLE_BOSS_ROOM, 0x0417},
{EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ROOM, WATER_TEMPLE_BOSS_ENTRYWAY, 0x0423, 0x060C}},
{{EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ENTRYWAY, SPIRIT_TEMPLE_BOSS_ROOM, 0x008D},
{EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_BOSS_ENTRYWAY, 0x02F5, 0x0610}},
{{EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ENTRYWAY, SHADOW_TEMPLE_BOSS_ROOM, 0x0413},
{EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ROOM, SHADOW_TEMPLE_BOSS_ENTRYWAY, 0x02B2, 0x0580}},
{ { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ENTRYWAY, RR_DEKU_TREE_BOSS_ROOM, 0x040F },
{ EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY, 0x0252, 0x0457 } },
{ { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, RR_DODONGOS_CAVERN_BOSS_ROOM, 0x040B },
{ EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, 0x00C5, 0x047A } },
{ { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, RR_JABU_JABUS_BELLY_BOSS_ROOM, 0x0301 },
{ EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, 0x0407, 0x010E } },
{ { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, RR_FOREST_TEMPLE_BOSS_ROOM, 0x000C },
{ EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, 0x024E, 0x0608 } },
{ { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, RR_FIRE_TEMPLE_BOSS_ROOM, 0x0305 },
{ EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, 0x0175, 0x0564 } },
{ { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ENTRYWAY, RR_WATER_TEMPLE_BOSS_ROOM, 0x0417 },
{ EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY, 0x0423, 0x060C } },
{ { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, RR_SPIRIT_TEMPLE_BOSS_ROOM, 0x008D },
{ EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, 0x02F5, 0x0610 } },
{ { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, 0x0413 },
{ EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, 0x02B2, 0x0580 } },
};
std::map<std::string, PriorityEntrance> priorityEntranceTable = {
{"Bolero", {{DMC_CENTRAL_LOCAL}, {EntranceType::OwlDrop, EntranceType::WarpSong}}},
{"Nocturne", {{GRAVEYARD_WARP_PAD_REGION}, {EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong}}},
{"Requiem", {{DESERT_COLOSSUS, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY}, {EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong}}},
{ "Bolero", { { RR_DMC_CENTRAL_LOCAL }, { EntranceType::OwlDrop, EntranceType::WarpSong } } },
{ "Nocturne",
{ { RR_GRAVEYARD_WARP_PAD_REGION }, { EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong } } },
{ "Requiem",
{ { RR_DESERT_COLOSSUS, RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY },
{ EntranceType::OwlDrop, EntranceType::Spawn, EntranceType::WarpSong } } },
};
entranceShuffleFailure = false;
@@ -1008,16 +1022,16 @@ int ShuffleAllEntrances() {
// If forest is closed, ensure Ghoma is inside the Deku tree
// Deku tree being in its vanilla location is handled below
if (Settings::OpenForest.Is(OPENFOREST_CLOSED) && !(Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances)) {
FilterAndEraseFromPool(entrancePools[EntranceType::Boss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == DEKU_TREE_BOSS_ENTRYWAY &&
entrance->GetConnectedRegionKey() == DEKU_TREE_BOSS_ROOM;});
FilterAndEraseFromPool(entrancePools[EntranceType::Boss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == RR_DEKU_TREE_BOSS_ENTRYWAY &&
entrance->GetConnectedRegionKey() == RR_DEKU_TREE_BOSS_ROOM;});
}
} else {
entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss);
entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss);
// If forest is closed, ensure Ghoma is inside the Deku tree
if (Settings::OpenForest.Is(OPENFOREST_CLOSED) && !(Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances)) {
FilterAndEraseFromPool(entrancePools[EntranceType::ChildBoss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == DEKU_TREE_BOSS_ENTRYWAY &&
entrance->GetConnectedRegionKey() == DEKU_TREE_BOSS_ROOM;});
FilterAndEraseFromPool(entrancePools[EntranceType::ChildBoss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == RR_DEKU_TREE_BOSS_ENTRYWAY &&
entrance->GetConnectedRegionKey() == RR_DEKU_TREE_BOSS_ROOM;});
}
}
}
@@ -1031,8 +1045,8 @@ int ShuffleAllEntrances() {
}
//If forest is closed don't allow a forest escape via spirit temple hands
if (Settings::OpenForest.Is(OPENFOREST_CLOSED) && !(Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances)) {
FilterAndEraseFromPool(entrancePools[EntranceType::Dungeon], [](const Entrance* entrance){return entrance->GetParentRegionKey() == KF_OUTSIDE_DEKU_TREE &&
entrance->GetConnectedRegionKey() == DEKU_TREE_ENTRYWAY;});
FilterAndEraseFromPool(entrancePools[EntranceType::Dungeon], [](const Entrance* entrance){return entrance->GetParentRegionKey() == RR_KF_OUTSIDE_DEKU_TREE &&
entrance->GetConnectedRegionKey() == RR_DEKU_TREE_ENTRYWAY;});
}
if (Settings::DecoupleEntrances) {
for (Entrance* entrance : entrancePools[EntranceType::Dungeon]) {
@@ -1072,8 +1086,8 @@ int ShuffleAllEntrances() {
entrancePools[EntranceType::Overworld] = GetShuffleableEntrances(EntranceType::Overworld, excludeOverworldReverse);
// Only shuffle GV Lower Stream -> Lake Hylia if decoupled entrances are on
if (!Settings::DecoupleEntrances) {
FilterAndEraseFromPool(entrancePools[EntranceType::Overworld], [](const Entrance* entrance){return entrance->GetParentRegionKey() == GV_LOWER_STREAM &&
entrance->GetConnectedRegionKey() == LAKE_HYLIA;});
FilterAndEraseFromPool(entrancePools[EntranceType::Overworld], [](const Entrance* entrance){return entrance->GetParentRegionKey() == RR_GV_LOWER_STREAM &&
entrance->GetConnectedRegionKey() == RR_LAKE_HYLIA;});
}
}
@@ -1135,7 +1149,7 @@ int ShuffleAllEntrances() {
if (poolType == EntranceType::OwlDrop) {
validTargetTypes = {EntranceType::WarpSong, EntranceType::OwlDrop, EntranceType::Overworld, EntranceType::Extra};
oneWayTargetEntrancePools[poolType] = BuildOneWayTargets(validTargetTypes, {std::make_pair(PRELUDE_OF_LIGHT_WARP, TEMPLE_OF_TIME)});
oneWayTargetEntrancePools[poolType] = BuildOneWayTargets(validTargetTypes, {std::make_pair(RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME)});
// Owl Drops are only accessible as child, so targets should reflect that
for (Entrance* target : oneWayTargetEntrancePools[poolType]) {
target->SetCondition([]{return Logic::IsChild;});

View File

@@ -1,6 +1,5 @@
#pragma once
#include "keys.hpp"
#include "location_access.hpp"
#include <string>
@@ -38,7 +37,7 @@ enum class EntranceType {
class Entrance {
public:
Entrance(uint32_t connectedRegion_, std::vector<ConditionFn> conditions_met_)
Entrance(RandomizerRegion connectedRegion_, std::vector<ConditionFn> conditions_met_)
: connectedRegion(connectedRegion_) {
conditions_met.resize(2);
for (size_t i = 0; i < conditions_met_.size(); i++) {
@@ -127,10 +126,10 @@ public:
age = true;
Logic::UpdateHelpers();
return GetConditionsMet() && (connectedRegion != NONE || passAnyway);
return GetConditionsMet() && (connectedRegion != RR_NONE || passAnyway);
}
uint32_t GetConnectedRegionKey() const {
RandomizerRegion GetConnectedRegionKey() const {
return connectedRegion;
}
@@ -138,11 +137,11 @@ public:
return AreaTable(connectedRegion);
}
void SetParentRegion(uint32_t newParent) {
void SetParentRegion(RandomizerRegion newParent) {
parentRegion = newParent;
}
uint32_t GetParentRegionKey() const {
RandomizerRegion GetParentRegionKey() const {
return parentRegion;
}
@@ -150,7 +149,7 @@ public:
return AreaTable(parentRegion);
}
void SetNewEntrance(uint32_t newRegion) {
void SetNewEntrance(RandomizerRegion newRegion) {
connectedRegion = newRegion;
}
@@ -230,15 +229,15 @@ public:
return reverse;
}
void Connect(uint32_t newConnectedRegion) {
void Connect(RandomizerRegion newConnectedRegion) {
connectedRegion = newConnectedRegion;
AreaTable(newConnectedRegion)->entrances.push_front(this);
}
uint32_t Disconnect() {
RandomizerRegion Disconnect() {
AreaTable(connectedRegion)->entrances.remove_if([this](const auto entrance){return this == entrance;});
uint32_t previouslyConnected = connectedRegion;
connectedRegion = NONE;
RandomizerRegion previouslyConnected = connectedRegion;
connectedRegion = RR_NONE;
return previouslyConnected;
}
@@ -248,8 +247,8 @@ public:
}
Entrance* GetNewTarget() {
AreaTable(ROOT)->AddExit(ROOT, connectedRegion, []{return true;});
Entrance* targetEntrance = AreaTable(ROOT)->GetExit(connectedRegion);
AreaTable(RR_ROOT)->AddExit(RR_ROOT, connectedRegion, []{return true;});
Entrance* targetEntrance = AreaTable(RR_ROOT)->GetExit(connectedRegion);
targetEntrance->SetReplacement(this);
targetEntrance->SetName(GetParentRegion()->regionName + " -> " + GetConnectedRegion()->regionName);
return targetEntrance;
@@ -264,8 +263,8 @@ public:
}
private:
uint32_t parentRegion;
uint32_t connectedRegion;
RandomizerRegion parentRegion;
RandomizerRegion connectedRegion;
std::vector<ConditionFn> conditions_met;
//Entrance Randomizer stuff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
#pragma once
#include "keys.hpp"
#include "../randomizerTypes.h"
#include <vector>
#include <string>
@@ -21,7 +21,7 @@ void ClearProgress();
void VanillaFill();
int Fill();
std::vector<uint32_t> GetAccessibleLocations(const std::vector<uint32_t>& allowedLocations,
std::vector<RandomizerCheck> GetAccessibleLocations(const std::vector<RandomizerCheck>& allowedLocations,
SearchMode mode = SearchMode::ReachabilitySearch, std::string ignore = "",
bool checkPoeCollectorAccess = false,
bool checkOtherEntranceAccess = false);

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,13 @@
#pragma once
#include "hints.hpp"
#include "keys.hpp"
#include <vector>
extern std::array<HintText, KEY_ENUM_MAX> hintTable;
extern std::array<HintText, RHT_MAX> hintTable;
void HintTable_Init();
const HintText& Hint(uint32_t hintKey);
const HintText& Hint(const RandomizerHintTextKey hintKey);
std::vector<HintText> GetHintCategory(HintCategory category);
void HintTable_Init_Item();

View File

@@ -2,7 +2,6 @@
#include "custom_messages.hpp"
#include "dungeon.hpp"
#include "item_location.hpp"
#include "item_pool.hpp"
#include "logic.hpp"
#include "random.hpp"
@@ -14,6 +13,7 @@
#include "z64item.h"
#include <spdlog/spdlog.h>
#include "../randomizerTypes.h"
#include "../context.h"
using namespace CustomMessages;
using namespace Logic;
@@ -215,24 +215,24 @@ std::string GetSariaHintLoc() {
return sariaHintLoc;
}
Area* GetHintRegion(const uint32_t area) {
Area* GetHintRegion(const RandomizerRegion area) {
std::vector<uint32_t> alreadyChecked = {};
std::vector<uint32_t> spotQueue = {area};
std::vector<RandomizerRegion> alreadyChecked = {};
std::vector<RandomizerRegion> spotQueue = {area};
while (!spotQueue.empty()) {
uint32_t region = spotQueue.back();
RandomizerRegion region = spotQueue.back();
alreadyChecked.push_back(region);
spotQueue.pop_back();
if (AreaTable(region)->hintKey != NONE) {
if (AreaTable(region)->hintKey != RHT_NONE) {
return AreaTable(region);
}
//add unchecked entrances to spot queue
bool checked = false;
for (auto& entrance : AreaTable(region)->entrances) {
for (uint32_t checkedEntrance : alreadyChecked) {
for (RandomizerRegion checkedEntrance : alreadyChecked) {
if (entrance->GetParentRegionKey() == checkedEntrance) {
checked = true;
break;
@@ -245,60 +245,63 @@ Area* GetHintRegion(const uint32_t area) {
}
}
return AreaTable(NONE);
return AreaTable(RR_NONE);
}
uint32_t GetHintRegionHintKey(const uint32_t area) {
RandomizerHintTextKey GetHintRegionHintKey(const RandomizerRegion area) {
return GetHintRegion(area)->hintKey;
}
uint32_t GetHintRegionuint32_t(const uint32_t area) {
uint32_t GetHintRegionuint32_t(const RandomizerRegion area) {
return GetHintRegion(area)->hintKey;
}
uint32_t GetLocationRegionuint32_t(const uint32_t location) {
return GetHintRegion(Location(location)->GetParentRegionKey())->hintKey;
uint32_t GetLocationRegionuint32_t(const RandomizerCheck location) {
return GetHintRegion(Rando::Context::GetInstance()->GetItemLocation(location)->GetParentRegionKey())->hintKey;
}
static std::vector<uint32_t> GetAccessibleGossipStones(const uint32_t hintedLocation = GANON) {
static std::vector<RandomizerCheck> GetAccessibleGossipStones(const RandomizerCheck hintedLocation = RC_GANON) {
auto ctx = Rando::Context::GetInstance();
//temporarily remove the hinted location's item, and then perform a
//reachability search for gossip stone locations.
uint32_t originalItem = Location(hintedLocation)->GetPlaceduint32_t();
Location(hintedLocation)->SetPlacedItem(NONE);
RandomizerGet originalItem = ctx->GetItemLocation(hintedLocation)->GetPlacedRandomizerGet();
ctx->GetItemLocation(hintedLocation)->SetPlacedItem(RG_NONE);
LogicReset();
auto accessibleGossipStones = GetAccessibleLocations(gossipStoneLocations);
auto accessibleGossipStones = GetAccessibleLocations(Rando::StaticData::gossipStoneLocations);
//Give the item back to the location
Location(hintedLocation)->SetPlacedItem(originalItem);
ctx->GetItemLocation(hintedLocation)->SetPlacedItem(originalItem);
return accessibleGossipStones;
}
static void AddHint(Text hint, const uint32_t gossipStone, const std::vector<uint8_t>& colors = {}, HintType hintType = HINT_TYPE_ITEM, const uint32_t hintedLocation = NONE) {
static void AddHint(Text hint, const RandomizerCheck gossipStone, const std::vector<uint8_t>& colors = {}, HintType hintType = HINT_TYPE_ITEM, const RandomizerCheck hintedLocation = RC_UNKNOWN_CHECK) {
//save hints as dummy items for writing to the spoiler log
NewItem(gossipStone, Item{RG_HINT, hint, ITEMTYPE_EVENT, GI_RUPEE_BLUE_LOSE, false, &noVariable, NONE});
Location(gossipStone)->SetPlacedItem(gossipStone);
Location(gossipStone)->SetHintedLocation(hintedLocation);
Location(gossipStone)->SetHintType(hintType);
Location(gossipStone)->SetHintedRegion(GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText().GetEnglish());
//NewItem(gossipStone, Item{RG_HINT, hint, ITEMTYPE_EVENT, GI_RUPEE_BLUE_LOSE, false, &noVariable, NONE});
//GetLocation(gossipStone)->SetPlacedItem(gossipStone);
auto ctx = Rando::Context::GetInstance();
ctx->AddHint((RandomizerHintKey)((gossipStone - RC_DMC_GOSSIP_STONE) + 1), hint, hintedLocation, hintType, GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText());
ctx->GetItemLocation(gossipStone)->SetPlacedItem(RG_HINT);
}
static void CreateLocationHint(const std::vector<uint32_t>& possibleHintLocations) {
static void CreateLocationHint(const std::vector<RandomizerCheck>& possibleHintLocations) {
auto ctx = Rando::Context::GetInstance();
//return if there aren't any hintable locations or gossip stones available
if (possibleHintLocations.empty()) {
SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n");
return;
}
uint32_t hintedLocation = RandomElement(possibleHintLocations);
const std::vector<uint32_t> accessibleGossipStones = GetAccessibleGossipStones(hintedLocation);
RandomizerCheck hintedLocation = RandomElement(possibleHintLocations);
const std::vector<RandomizerCheck> accessibleGossipStones = GetAccessibleGossipStones(hintedLocation);
SPDLOG_DEBUG("\tLocation: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetName());
SPDLOG_DEBUG(Rando::StaticData::GetLocation(hintedLocation)->GetName());
SPDLOG_DEBUG("\n");
SPDLOG_DEBUG("\tItem: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG(ctx->GetItemLocation(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG("\n");
if (accessibleGossipStones.empty()) {
@@ -306,13 +309,13 @@ static void CreateLocationHint(const std::vector<uint32_t>& possibleHintLocation
return;
}
uint32_t gossipStone = RandomElement(accessibleGossipStones);
Location(hintedLocation)->SetAsHinted();
RandomizerCheck gossipStone = RandomElement(accessibleGossipStones);
ctx->GetItemLocation(hintedLocation)->SetAsHinted();
//make hint text
Text locationHintText = Location(hintedLocation)->GetHint().GetText();
Text itemHintText = Location(hintedLocation)->GetPlacedItem().GetHint().GetText();
Text prefix = Hint(PREFIX).GetText();
Text locationHintText = Rando::StaticData::GetLocation(hintedLocation)->GetHint()->GetText();
Text itemHintText = ctx->GetItemLocation(hintedLocation)->GetPlacedItem().GetHint().GetText();
Text prefix = Hint(RHT_PREFIX).GetText();
Text finalHint = prefix + "%r" + locationHintText + " #%g" + itemHintText + "#%w.";
SPDLOG_DEBUG("\tMessage: ");
@@ -323,15 +326,16 @@ static void CreateLocationHint(const std::vector<uint32_t>& possibleHintLocation
}
static void CreateWothHint(uint8_t* remainingDungeonWothHints) {
auto ctx = Rando::Context::GetInstance();
// get locations that are in the current playthrough
std::vector<uint32_t> possibleHintLocations = {};
std::vector<RandomizerCheck> possibleHintLocations = {};
// iterate through playthrough locations by sphere
std::vector<uint32_t> wothHintLocations =
FilterFromPool(wothLocations, [remainingDungeonWothHints](uint32_t loc) {
return Location(loc)->IsHintable() && // only filter hintable locations
!(Location(loc)->IsHintedAt()) && // only filter locations that haven't been hinted at
(Location(loc)->IsOverworld() ||
(Location(loc)->IsDungeon() &&
std::vector<RandomizerCheck> wothHintLocations =
FilterFromPool(ctx->wothLocations, [remainingDungeonWothHints, ctx](RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->IsHintable() && // only filter hintable locations
!(ctx->GetItemLocation(loc)->IsHintedAt()) && // only filter locations that haven't been hinted at
(Rando::StaticData::GetLocation(loc)->IsOverworld() ||
(Rando::StaticData::GetLocation(loc)->IsDungeon() &&
(*remainingDungeonWothHints) > 0)); // make sure we haven't surpassed the woth dungeon limit
});
AddElementsToPool(possibleHintLocations, wothHintLocations);
@@ -341,129 +345,133 @@ static void CreateWothHint(uint8_t* remainingDungeonWothHints) {
SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n");
return;
}
uint32_t hintedLocation = RandomElement(possibleHintLocations);
RandomizerCheck hintedLocation = RandomElement(possibleHintLocations);
SPDLOG_DEBUG("\tLocation: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetName());
SPDLOG_DEBUG(Rando::StaticData::GetLocation(hintedLocation)->GetName());
SPDLOG_DEBUG("\n");
SPDLOG_DEBUG("\tItem: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG(ctx->GetItemLocation(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG("\n");
// get an accessible gossip stone
const std::vector<uint32_t> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
const std::vector<RandomizerCheck> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
if (gossipStoneLocations.empty()) {
SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n");
return;
}
Location(hintedLocation)->SetAsHinted();
uint32_t gossipStone = RandomElement(gossipStoneLocations);
ctx->GetItemLocation(hintedLocation)->SetAsHinted();
RandomizerCheck gossipStone = RandomElement(gossipStoneLocations);
if (Location(hintedLocation)->IsDungeon()) {
if (Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()) {
*remainingDungeonWothHints -= 1;
}
// form hint text
Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
Text finalWothHint = Hint(PREFIX).GetText() + "%r#" + locationText + "#%w" + Hint(WAY_OF_THE_HERO).GetText();
Text locationText = GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
Text finalWothHint = Hint(RHT_PREFIX).GetText() + "%r#" + locationText + "#%w" + Hint(RHT_WAY_OF_THE_HERO).GetText();
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalWothHint.english);
SPDLOG_DEBUG("\n\n");
AddHint(finalWothHint, gossipStone, { QM_LBLUE }, HINT_TYPE_WOTH, hintedLocation);
}
static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vector<uint32_t>& barrenLocations) {
static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vector<RandomizerCheck>& barrenLocations) {
auto ctx = Rando::Context::GetInstance();
// remove dungeon locations if necessary
if (*remainingDungeonBarrenHints < 1) {
barrenLocations =
FilterFromPool(barrenLocations, [](const uint32_t loc) { return !(Location(loc)->IsDungeon()); });
FilterFromPool(barrenLocations, [](const RandomizerCheck loc) {
return !(Rando::StaticData::GetLocation(loc)->IsDungeon());
});
}
if (barrenLocations.empty()) {
return;
}
uint32_t hintedLocation = RandomElement(barrenLocations, true);
RandomizerCheck hintedLocation = RandomElement(barrenLocations, true);
SPDLOG_DEBUG("\tLocation: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetName());
SPDLOG_DEBUG(Rando::StaticData::GetLocation(hintedLocation)->GetName());
SPDLOG_DEBUG("\n");
SPDLOG_DEBUG("\tItem: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG(ctx->GetItemLocation(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG("\n");
// get an accessible gossip stone
const std::vector<uint32_t> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
const std::vector<RandomizerCheck> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
if (gossipStoneLocations.empty()) {
SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n");
return;
}
Location(hintedLocation)->SetAsHinted();
uint32_t gossipStone = RandomElement(gossipStoneLocations);
ctx->GetItemLocation(hintedLocation)->SetAsHinted();
RandomizerCheck gossipStone = RandomElement(gossipStoneLocations);
if (Location(hintedLocation)->IsDungeon()) {
if (Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()) {
*remainingDungeonBarrenHints -= 1;
}
// form hint text
Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
Text locationText = GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
Text finalBarrenHint =
Hint(PREFIX).GetText() + Hint(PLUNDERING).GetText() + "%r#" + locationText + "#%w" + Hint(FOOLISH).GetText();
Hint(RHT_PREFIX).GetText() + Hint(RHT_PLUNDERING).GetText() + "%r#" + locationText + "#%w" + Hint(RHT_FOOLISH).GetText();
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalBarrenHint.english);
SPDLOG_DEBUG("\n\n");
AddHint(finalBarrenHint, gossipStone, { QM_PINK }, HINT_TYPE_BARREN, hintedLocation);
// get rid of all other locations in this same barren region
barrenLocations = FilterFromPool(barrenLocations, [hintedLocation](uint32_t loc) {
return GetHintRegion(Location(loc)->GetParentRegionKey())->hintKey !=
GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->hintKey;
barrenLocations = FilterFromPool(barrenLocations, [hintedLocation, ctx](RandomizerCheck loc) {
return GetHintRegion(ctx->GetItemLocation(loc)->GetParentRegionKey())->hintKey !=
GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->hintKey;
});
}
static void CreateRandomLocationHint(const bool goodItem = false) {
const std::vector<uint32_t> possibleHintLocations = FilterFromPool(allLocations, [goodItem](const uint32_t loc) {
return Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt()) && (!goodItem || Location(loc)->GetPlacedItem().IsMajorItem());
auto ctx = Rando::Context::GetInstance();
const std::vector<RandomizerCheck> possibleHintLocations = FilterFromPool(ctx->allLocations, [goodItem, ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsHintedAt()) && (!goodItem || ctx->GetItemLocation(loc)->GetPlacedItem().IsMajorItem());
});
//If no more locations can be hinted at, then just try to get another hint
if (possibleHintLocations.empty()) {
SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n");
return;
}
uint32_t hintedLocation = RandomElement(possibleHintLocations);
RandomizerCheck hintedLocation = RandomElement(possibleHintLocations);
SPDLOG_DEBUG("\tLocation: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetName());
SPDLOG_DEBUG(Rando::StaticData::GetLocation(hintedLocation)->GetName());
SPDLOG_DEBUG("\n");
SPDLOG_DEBUG("\tItem: ");
SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG(ctx->GetItemLocation(hintedLocation)->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG("\n");
//get an acessible gossip stone
const std::vector<uint32_t> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
const std::vector<RandomizerCheck> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
if (gossipStoneLocations.empty()) {
SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n");
return;
}
Location(hintedLocation)->SetAsHinted();
uint32_t gossipStone = RandomElement(gossipStoneLocations);
ctx->GetItemLocation(hintedLocation)->SetAsHinted();
RandomizerCheck gossipStone = RandomElement(gossipStoneLocations);
//form hint text
Text itemText = Location(hintedLocation)->GetPlacedItem().GetHint().GetText();
Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
Text itemText = ctx->GetItemLocation(hintedLocation)->GetPlacedItem().GetHint().GetText();
Text locationText = GetHintRegion(ctx->GetItemLocation(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
// RANDOTODO: reconsider dungeon vs non-dungeon item location hints when boss shuffle mixed pools happens
if (Location(hintedLocation)->IsDungeon()) {
Text finalHint = Hint(PREFIX).GetText()+"%r#"+locationText+"#%w "+Hint(HOARDS).GetText()+" %g#"+itemText+"#%w.";
if (Rando::StaticData::GetLocation(hintedLocation)->IsDungeon()) {
Text finalHint = Hint(RHT_PREFIX).GetText()+"%r#"+locationText+"#%w "+Hint(RHT_HOARDS).GetText()+" %g#"+itemText+"#%w.";
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalHint.english);
SPDLOG_DEBUG("\n\n");
AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED}, HINT_TYPE_NAMED_ITEM, hintedLocation);
} else {
Text finalHint = Hint(PREFIX).GetText()+"%r#"+itemText+"#%w "+Hint(CAN_BE_FOUND_AT).GetText()+" %g#"+locationText+"#%w.";
Text finalHint = Hint(RHT_PREFIX).GetText()+"%r#"+itemText+"#%w "+Hint(RHT_CAN_BE_FOUND_AT).GetText()+" %g#"+locationText+"#%w.";
SPDLOG_DEBUG("\tMessage: ");
SPDLOG_DEBUG(finalHint.english);
SPDLOG_DEBUG("\n\n");
@@ -479,12 +487,12 @@ static void CreateJunkHint() {
//duplicate junk hints are possible for now
const HintText junkHint = RandomElement(GetHintCategory(HintCategory::Junk));
LogicReset();
const std::vector<uint32_t> gossipStones = GetAccessibleLocations(gossipStoneLocations);
const std::vector<RandomizerCheck> gossipStones = GetAccessibleLocations(Rando::StaticData::gossipStoneLocations);
if (gossipStones.empty()) {
SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n");
return;
}
uint32_t gossipStone = RandomElement(gossipStones);
RandomizerCheck gossipStone = RandomElement(gossipStones);
Text hint = junkHint.GetText();
SPDLOG_DEBUG("\tMessage: ");
@@ -494,26 +502,27 @@ static void CreateJunkHint() {
AddHint(hint, gossipStone, { QM_PINK }, HINT_TYPE_JUNK);
}
static std::vector<uint32_t> CalculateBarrenRegions() {
std::vector<uint32_t> barrenLocations = {};
std::vector<uint32_t> potentiallyUsefulLocations = {};
static std::vector<RandomizerCheck> CalculateBarrenRegions() {
auto ctx = Rando::Context::GetInstance();
std::vector<RandomizerCheck> barrenLocations = {};
std::vector<RandomizerCheck> potentiallyUsefulLocations = {};
for (uint32_t loc : allLocations) {
for (RandomizerCheck loc : ctx->allLocations) {
// If a location has a major item or is a way of the hero location, it is not barren
if (Location(loc)->GetPlacedItem().IsMajorItem() || ElementInContainer(loc, wothLocations)) {
if (ctx->GetItemLocation(loc)->GetPlacedItem().IsMajorItem() || ElementInContainer(loc, ctx->wothLocations)) {
AddElementsToPool(potentiallyUsefulLocations, std::vector{loc});
} else {
// Link's Pocket & Triforce Hunt "reward" shouldn't be considered for barren areas because it's clear what
// they have to a player.
if (loc != LINKS_POCKET && loc != TRIFORCE_COMPLETED) {
if (loc != RC_LINKS_POCKET && loc != RC_TRIFORCE_COMPLETED) {
AddElementsToPool(barrenLocations, std::vector{loc});
}
}
}
// Leave only locations at barren regions in the list
auto finalBarrenLocations = FilterFromPool(barrenLocations, [&potentiallyUsefulLocations](uint32_t loc){
for (uint32_t usefulLoc : potentiallyUsefulLocations) {
auto finalBarrenLocations = FilterFromPool(barrenLocations, [&potentiallyUsefulLocations](RandomizerCheck loc){
for (RandomizerCheck usefulLoc : potentiallyUsefulLocations) {
uint32_t barrenKey = GetLocationRegionuint32_t(loc);
uint32_t usefulKey = GetLocationRegionuint32_t(usefulLoc);
if (barrenKey == usefulKey) {
@@ -535,7 +544,7 @@ static void CreateTrialHints() {
auto gossipStone = RandomElement(gossipStones, false);
//make hint
auto hint = Hint(PREFIX).GetText() + Hint(SIX_TRIALS).GetText();
auto hint = Hint(RHT_PREFIX).GetText() + Hint(RHT_SIX_TRIALS).GetText();
AddHint(hint, gossipStone, { QM_PINK }, HINT_TYPE_TRIAL);
//zero trials
@@ -546,7 +555,7 @@ static void CreateTrialHints() {
auto gossipStone = RandomElement(gossipStones, false);
//make hint
auto hint = Hint(PREFIX).GetText() + Hint(ZERO_TRIALS).GetText();
auto hint = Hint(RHT_PREFIX).GetText() + Hint(RHT_ZERO_TRIALS).GetText();
AddHint(hint, gossipStone, { QM_YELLOW }, HINT_TYPE_TRIAL);
//4 or 5 required trials
@@ -564,7 +573,7 @@ static void CreateTrialHints() {
auto gossipStone = RandomElement(gossipStones, false);
//make hint
auto hint = Hint(PREFIX).GetText()+"#"+trial->GetName()+"#"+Hint(FOUR_TO_FIVE_TRIALS).GetText();
auto hint = Hint(RHT_PREFIX).GetText()+"#"+trial->GetName()+"#"+Hint(RHT_FOUR_TO_FIVE_TRIALS).GetText();
AddHint(hint, gossipStone, { QM_YELLOW }, HINT_TYPE_TRIAL);
}
//1 to 3 trials
@@ -581,44 +590,54 @@ static void CreateTrialHints() {
auto gossipStone = RandomElement(gossipStones, false);
//make hint
auto hint = Hint(PREFIX).GetText()+"#"+trial->GetName()+"#"+Hint(ONE_TO_THREE_TRIALS).GetText();
auto hint = Hint(RHT_PREFIX).GetText()+"#"+trial->GetName()+"#"+Hint(RHT_ONE_TO_THREE_TRIALS).GetText();
AddHint(hint, gossipStone, { QM_PINK }, HINT_TYPE_TRIAL);
}
}
}
void CreateGanonText() {
auto ctx = Rando::Context::GetInstance();
//funny ganon line
ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText();
CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText));
//Get the location of the light arrows
auto lightArrowLocation = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == LIGHT_ARROWS;});
auto lightArrowLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_LIGHT_ARROWS;
});
//If there is no light arrow location, it was in the player's inventory at the start
auto hint = Hint(LIGHT_ARROW_LOCATION_HINT);
auto hint = Hint(RHT_LIGHT_ARROW_LOCATION_HINT);
if (lightArrowLocation.empty()) {
ganonHintText = hint.GetText()+Hint(YOUR_POCKET).GetText();
ganonHintText = hint.GetText()+Hint(RHT_YOUR_POCKET).GetText();
lightArrowHintLoc = "Link's Pocket";
} else {
ganonHintText = hint.GetText() + "%r" + GetHintRegion(Location(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
lightArrowHintLoc = Location(lightArrowLocation[0])->GetName();
ganonHintText =
hint.GetText() + "%r" +
GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
lightArrowHintLoc = Rando::StaticData::GetLocation(lightArrowLocation[0])->GetName();
}
ganonHintText = ganonHintText + "!";
CreateMessageFromTextObject(0x70CC, 0, 2, 3, AddColorsAndFormat(ganonHintText));
ctx->AddHint(RH_GANONDORF_HINT, ganonHintText, lightArrowLocation[0], HINT_TYPE_STATIC, GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText());
}
//Find the location which has the given itemKey and create the generic altar text for the reward
static Text BuildDungeonRewardText(const uint32_t itemKey) {
uint32_t location = FilterFromPool(allLocations, [itemKey](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == itemKey;})[0];
Location(location)->SetAsHinted();
static Text BuildDungeonRewardText(const RandomizerGet itemKey) {
auto ctx = Rando::Context::GetInstance();
RandomizerCheck location = FilterFromPool(ctx->allLocations, [itemKey, ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == itemKey;
})[0];
ctx->GetItemLocation(location)->SetAsHinted();
std::string rewardString = "$" + std::to_string(itemKey - KOKIRI_EMERALD);
std::string rewardString = "$" + std::to_string(itemKey - RG_KOKIRI_EMERALD);
// RANDOTODO implement colors for locations
return Text()+rewardString+GetHintRegion(Location(location)->GetParentRegionKey())->GetHint().GetText().Capitalize()+"...^";
// RANDOTODO implement colors for locations
return Text() + rewardString +
GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText().Capitalize() +
"...^";
}
static Text BuildDoorOfTimeText() {
@@ -627,22 +646,22 @@ static Text BuildDoorOfTimeText() {
if (OpenDoorOfTime.Is(OPENDOOROFTIME_OPEN)) {
itemObtained = "$o";
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTOPEN).GetText();
doorOfTimeText = Hint(RHT_CHILD_ALTAR_TEXT_END_DOTOPEN).GetText();
} else if (OpenDoorOfTime.Is(OPENDOOROFTIME_SONGONLY)) {
itemObtained = "$c";
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTSONGONLY).GetText();
doorOfTimeText = Hint(RHT_CHILD_ALTAR_TEXT_END_DOTSONGONLY).GetText();
} else if (OpenDoorOfTime.Is(OPENDOOROFTIME_CLOSED)) {
itemObtained = "$i";
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTCLOSED).GetText();
doorOfTimeText = Hint(RHT_CHILD_ALTAR_TEXT_END_DOTCLOSED).GetText();
}
return Text()+itemObtained+doorOfTimeText;
}
//insert the required number into the hint and set the singular/plural form
static Text BuildCountReq(const uint32_t req, const Option& count) {
static Text BuildCountReq(const RandomizerHintTextKey req, const Option& count) {
Text requirement = Hint(req).GetTextCopy();
if (count.Value<uint8_t>() == 1) {
requirement.SetForm(SINGULAR);
@@ -657,28 +676,28 @@ static Text BuildBridgeReqsText() {
Text bridgeText;
if (Bridge.Is(RAINBOWBRIDGE_OPEN)) {
bridgeText = Hint(BRIDGE_OPEN_HINT).GetText();
bridgeText = Hint(RHT_BRIDGE_OPEN_HINT).GetText();
} else if (Bridge.Is(RAINBOWBRIDGE_VANILLA)) {
bridgeText = Hint(BRIDGE_VANILLA_HINT).GetText();
bridgeText = Hint(RHT_BRIDGE_VANILLA_HINT).GetText();
} else if (Bridge.Is(RAINBOWBRIDGE_STONES)) {
bridgeText = BuildCountReq(BRIDGE_STONES_HINT, BridgeStoneCount);
bridgeText = BuildCountReq(RHT_BRIDGE_STONES_HINT, BridgeStoneCount);
} else if (Bridge.Is(RAINBOWBRIDGE_MEDALLIONS)) {
bridgeText = BuildCountReq(BRIDGE_MEDALLIONS_HINT, BridgeMedallionCount);
bridgeText = BuildCountReq(RHT_BRIDGE_MEDALLIONS_HINT, BridgeMedallionCount);
} else if (Bridge.Is(RAINBOWBRIDGE_REWARDS)) {
bridgeText = BuildCountReq(BRIDGE_REWARDS_HINT, BridgeRewardCount);
bridgeText = BuildCountReq(RHT_BRIDGE_REWARDS_HINT, BridgeRewardCount);
} else if (Bridge.Is(RAINBOWBRIDGE_DUNGEONS)) {
bridgeText = BuildCountReq(BRIDGE_DUNGEONS_HINT, BridgeDungeonCount);
bridgeText = BuildCountReq(RHT_BRIDGE_DUNGEONS_HINT, BridgeDungeonCount);
} else if (Bridge.Is(RAINBOWBRIDGE_TOKENS)) {
bridgeText = BuildCountReq(BRIDGE_TOKENS_HINT, BridgeTokenCount);
bridgeText = BuildCountReq(RHT_BRIDGE_TOKENS_HINT, BridgeTokenCount);
} else if (Bridge.Is(RAINBOWBRIDGE_GREG)) {
bridgeText = Hint(BRIDGE_GREG_HINT).GetText();
bridgeText = Hint(RHT_BRIDGE_GREG_HINT).GetText();
}
return Text()+"$l"+bridgeText+"^";
@@ -688,88 +707,90 @@ static Text BuildGanonBossKeyText() {
Text ganonBossKeyText;
if (GanonsBossKey.Is(GANONSBOSSKEY_START_WITH)) {
ganonBossKeyText = Hint(GANON_BK_START_WITH_HINT).GetText();
ganonBossKeyText = Hint(RHT_GANON_BK_START_WITH_HINT).GetText();
} else if (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA)) {
ganonBossKeyText = Hint(GANON_BK_VANILLA_HINT).GetText();
ganonBossKeyText = Hint(RHT_GANON_BK_VANILLA_HINT).GetText();
} else if (GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON)) {
ganonBossKeyText = Hint(GANON_BK_OWN_DUNGEON_HINT).GetText();
ganonBossKeyText = Hint(RHT_GANON_BK_OWN_DUNGEON_HINT).GetText();
} else if (GanonsBossKey.Is(GANONSBOSSKEY_ANY_DUNGEON)) {
ganonBossKeyText = Hint(GANON_BK_ANY_DUNGEON_HINT).GetText();
ganonBossKeyText = Hint(RHT_GANON_BK_ANY_DUNGEON_HINT).GetText();
} else if (GanonsBossKey.Is(GANONSBOSSKEY_OVERWORLD)) {
ganonBossKeyText = Hint(GANON_BK_OVERWORLD_HINT).GetText();
ganonBossKeyText = Hint(RHT_GANON_BK_OVERWORLD_HINT).GetText();
} else if (GanonsBossKey.Is(GANONSBOSSKEY_ANYWHERE)) {
ganonBossKeyText = Hint(GANON_BK_ANYWHERE_HINT).GetText();
ganonBossKeyText = Hint(RHT_GANON_BK_ANYWHERE_HINT).GetText();
} else if (GanonsBossKey.Is(GANONSBOSSKEY_FINAL_GS_REWARD)) {
ganonBossKeyText = Hint(GANON_BK_SKULLTULA_HINT).GetText();
ganonBossKeyText = Hint(RHT_GANON_BK_SKULLTULA_HINT).GetText();
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_VANILLA)) {
ganonBossKeyText = Hint(LACS_VANILLA_HINT).GetText();
ganonBossKeyText = Hint(RHT_LACS_VANILLA_HINT).GetText();
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_STONES)) {
ganonBossKeyText = BuildCountReq(LACS_STONES_HINT, LACSStoneCount);
ganonBossKeyText = BuildCountReq(RHT_LACS_STONES_HINT, LACSStoneCount);
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_MEDALLIONS)) {
ganonBossKeyText = BuildCountReq(LACS_MEDALLIONS_HINT, LACSMedallionCount);
ganonBossKeyText = BuildCountReq(RHT_LACS_MEDALLIONS_HINT, LACSMedallionCount);
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_REWARDS)) {
ganonBossKeyText = BuildCountReq(LACS_REWARDS_HINT, LACSRewardCount);
ganonBossKeyText = BuildCountReq(RHT_LACS_REWARDS_HINT, LACSRewardCount);
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_DUNGEONS)) {
ganonBossKeyText = BuildCountReq(LACS_DUNGEONS_HINT, LACSDungeonCount);
ganonBossKeyText = BuildCountReq(RHT_LACS_DUNGEONS_HINT, LACSDungeonCount);
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_TOKENS)) {
ganonBossKeyText = BuildCountReq(LACS_TOKENS_HINT, LACSTokenCount);
ganonBossKeyText = BuildCountReq(RHT_LACS_TOKENS_HINT, LACSTokenCount);
} else if (GanonsBossKey.Is(GANONSBOSSKEY_TRIFORCE_HUNT)) {
ganonBossKeyText = Hint(GANON_BK_TRIFORCE_HINT).GetText();
ganonBossKeyText = Hint(RHT_GANON_BK_TRIFORCE_HINT).GetText();
}
return Text()+"$b"+ganonBossKeyText+"^";
}
void CreateAltarText() {
auto ctx = Rando::Context::GetInstance();
//Child Altar Text
if (AltarHintText) {
childAltarText = Hint(SPIRITUAL_STONE_TEXT_START).GetText()+"^"+
childAltarText = Hint(RHT_SPIRITUAL_STONE_TEXT_START).GetText()+"^"+
//Spiritual Stones
(StartingKokiriEmerald.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(KOKIRI_EMERALD)) +
: BuildDungeonRewardText(RG_KOKIRI_EMERALD)) +
(StartingGoronRuby.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(GORON_RUBY)) +
: BuildDungeonRewardText(RG_GORON_RUBY)) +
(StartingZoraSapphire.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(ZORA_SAPPHIRE)) +
: BuildDungeonRewardText(RG_ZORA_SAPPHIRE)) +
//How to open Door of Time, the event trigger is necessary to read the altar multiple times
BuildDoorOfTimeText();
} else {
childAltarText = BuildDoorOfTimeText();
}
ctx->AddHint(RH_ALTAR_CHILD, childAltarText, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
CreateMessageFromTextObject(0x7040, 0, 2, 3, AddColorsAndFormat(childAltarText, {QM_GREEN, QM_RED, QM_BLUE}));
//Adult Altar Text
adultAltarText = Hint(ADULT_ALTAR_TEXT_START).GetText() + "^";
adultAltarText = Hint(RHT_ADULT_ALTAR_TEXT_START).GetText() + "^";
if (AltarHintText) {
adultAltarText = adultAltarText +
//Medallion Areas
(StartingLightMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(LIGHT_MEDALLION)) +
: BuildDungeonRewardText(RG_LIGHT_MEDALLION)) +
(StartingForestMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(FOREST_MEDALLION)) +
: BuildDungeonRewardText(RG_FOREST_MEDALLION)) +
(StartingFireMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(FIRE_MEDALLION)) +
: BuildDungeonRewardText(RG_FIRE_MEDALLION)) +
(StartingWaterMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(WATER_MEDALLION)) +
: BuildDungeonRewardText(RG_WATER_MEDALLION)) +
(StartingSpiritMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(SPIRIT_MEDALLION)) +
: BuildDungeonRewardText(RG_SPIRIT_MEDALLION)) +
(StartingShadowMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
: BuildDungeonRewardText(SHADOW_MEDALLION));
: BuildDungeonRewardText(RG_SHADOW_MEDALLION));
}
adultAltarText = adultAltarText +
//Bridge requirement
@@ -779,40 +800,53 @@ void CreateAltarText() {
BuildGanonBossKeyText()+
//End
Hint(ADULT_ALTAR_TEXT_END).GetText();
Hint(RHT_ADULT_ALTAR_TEXT_END).GetText();
CreateMessageFromTextObject(0x7088, 0, 2, 3, AddColorsAndFormat(adultAltarText, {QM_RED, QM_YELLOW, QM_GREEN, QM_RED, QM_BLUE, QM_YELLOW, QM_PINK, QM_RED, QM_RED, QM_RED, QM_RED}));
ctx->AddHint(RH_ALTAR_ADULT, adultAltarText, RC_UNKNOWN_CHECK, HINT_TYPE_STATIC, Text());
}
void CreateMerchantsHints() {
auto ctx = Rando::Context::GetInstance();
Text medigoronItemText = ctx->GetItemLocation(RC_GC_MEDIGORON)->GetPlacedItem().GetHint().GetText();
Text grannyItemText = ctx->GetItemLocation(RC_KAK_GRANNYS_SHOP)->GetPlacedItem().GetHint().GetText();
Text carpetSalesmanItemText =
ctx->GetItemLocation(RC_WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetText();
Text carpetSalesmanItemClearText =
ctx->GetItemLocation(RC_WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetClear();
Text medigoronItemText = Location(GC_MEDIGORON)->GetPlacedItem().GetHint().GetText();
Text grannyItemText = Location(KAK_GRANNYS_SHOP)->GetPlacedItem().GetHint().GetText();
Text carpetSalesmanItemText = Location(WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetText();
Text carpetSalesmanItemClearText = Location(WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetClear();
Text grannyCapitalItemText = grannyItemText.Capitalize();
Text grannyCapitalItemText = grannyItemText.Capitalize();
Text medigoronText =
Hint(RHT_MEDIGORON_DIALOG_FIRST).GetText() + medigoronItemText + Hint(RHT_MEDIGORON_DIALOG_SECOND).GetText();
Text grannyText = grannyCapitalItemText + Hint(RHT_GRANNY_DIALOG).GetText();
Text carpetSalesmanTextOne = Hint(RHT_CARPET_SALESMAN_DIALOG_FIRST).GetText() + carpetSalesmanItemText +
Hint(RHT_CARPET_SALESMAN_DIALOG_SECOND).GetText();
Text carpetSalesmanTextTwo = Hint(RHT_CARPET_SALESMAN_DIALOG_THIRD).GetText() + carpetSalesmanItemClearText +
Hint(RHT_CARPET_SALESMAN_DIALOG_FOURTH).GetText();
Text medigoronText = Hint(MEDIGORON_DIALOG_FIRST).GetText()+medigoronItemText+Hint(MEDIGORON_DIALOG_SECOND).GetText();
Text grannyText = grannyCapitalItemText+Hint(GRANNY_DIALOG).GetText();
Text carpetSalesmanTextOne = Hint(CARPET_SALESMAN_DIALOG_FIRST).GetText()+carpetSalesmanItemText+Hint(CARPET_SALESMAN_DIALOG_SECOND).GetText();
Text carpetSalesmanTextTwo = Hint(CARPET_SALESMAN_DIALOG_THIRD).GetText()+carpetSalesmanItemClearText+Hint(CARPET_SALESMAN_DIALOG_FOURTH).GetText();
CreateMessageFromTextObject(0x9120, 0, 2, 3, AddColorsAndFormat(medigoronText, {QM_RED, QM_GREEN}));
CreateMessageFromTextObject(0x9121, 0, 2, 3, AddColorsAndFormat(grannyText, {QM_RED, QM_GREEN}));
CreateMessageFromTextObject(0x6077, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextOne, {QM_RED, QM_GREEN}));
CreateMessageFromTextObject(0x6078, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextTwo, {QM_RED, QM_YELLOW, QM_RED}));
CreateMessageFromTextObject(0x9120, 0, 2, 3, AddColorsAndFormat(medigoronText, { QM_RED, QM_GREEN }));
CreateMessageFromTextObject(0x9121, 0, 2, 3, AddColorsAndFormat(grannyText, { QM_RED, QM_GREEN }));
CreateMessageFromTextObject(0x6077, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextOne, { QM_RED, QM_GREEN }));
CreateMessageFromTextObject(0x6078, 0, 2, 3,
AddColorsAndFormat(carpetSalesmanTextTwo, { QM_RED, QM_YELLOW, QM_RED }));
ctx->AddHint(RH_MEDIGORON, medigoronText, RC_GC_MEDIGORON, HINT_TYPE_STATIC, GetHintRegion(RR_GORON_CITY)->GetHint().GetText());
ctx->AddHint(RH_GRANNYS_SHOP, grannyText, RC_KAK_GRANNYS_SHOP, HINT_TYPE_STATIC, GetHintRegion(RR_KAKARIKO_VILLAGE)->GetHint().GetText());
ctx->AddHint(RH_WASTELAND_BOMBCHU_SALESMAN, carpetSalesmanTextOne, RC_WASTELAND_BOMBCHU_SALESMAN, HINT_TYPE_STATIC, GetHintRegion(RR_HAUNTED_WASTELAND)->GetHint().GetText());
}
void CreateDampesDiaryText() {
auto ctx = Rando::Context::GetInstance();
if (!DampeHintText) {
dampesText = Text();
dampeHintLoc = "";
return;
}
uint32_t item = PROGRESSIVE_HOOKSHOT;
uint32_t location = FilterFromPool(allLocations, [item](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == item;})[0];
Text area = GetHintRegion(Location(location)->GetParentRegionKey())->GetHint().GetText();
RandomizerGet item = RG_PROGRESSIVE_HOOKSHOT;
RandomizerCheck location = FilterFromPool(ctx->allLocations, [item, ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == item;
})[0];
Text area = GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{
"Whoever reads this, please enter %r",
"Toi qui lit ce journal, rends-toi dans %r",
@@ -826,17 +860,21 @@ void CreateDampesDiaryText() {
};
dampesText = temp1 + area + temp2;
dampeHintLoc = Location(location)->GetName();
dampeHintLoc = Rando::StaticData::GetLocation(location)->GetName();
ctx->AddHint(RH_DAMPES_DIARY, dampesText, location, HINT_TYPE_STATIC, area);
}
void CreateGregRupeeHint() {
auto ctx = Rando::Context::GetInstance();
if (!GregHintText) {
gregText = Text();
return;
}
uint32_t location = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->GetPlacedItemKey() == GREG_RUPEE;})[0];
Text area = GetHintRegion(Location(location)->GetParentRegionKey())->GetHint().GetText();
RandomizerCheck location = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE;
})[0];
Text area = GetHintRegion(ctx->GetItemLocation(location)->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{
"By the way, if you're interested, I saw the shiniest %gGreen Rupee%w somewhere in%r ",
@@ -851,13 +889,15 @@ void CreateGregRupeeHint() {
};
gregText = temp1 + area + temp2;
ctx->AddHint(RH_GREG_RUPEE, gregText, location, HINT_TYPE_STATIC, area);
}
void CreateSheikText() {
auto ctx = Rando::Context::GetInstance();
//Get the location of the light arrows
auto lightArrowLocation = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == LIGHT_ARROWS;});
lightArrowHintLoc = Location(lightArrowLocation[0])->GetName();
Text area = GetHintRegion(Location(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
auto lightArrowLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc){return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_LIGHT_ARROWS;});
lightArrowHintLoc = Rando::StaticData::GetLocation(lightArrowLocation[0])->GetName();
Text area = GetHintRegion(ctx->GetItemLocation(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{
"I overheard Ganondorf say that he misplaced the %yLight Arrows%w in&%r",
"J'ai entendu dire que Ganondorf aurait caché les %yFlèches de Lumière%w dans %r",
@@ -868,10 +908,11 @@ void CreateSheikText() {
}
void CreateSariaText() {
//Get the location of the light arrows
auto magicLocation = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == PROGRESSIVE_MAGIC_METER;});
sariaHintLoc = Location(magicLocation[0])->GetName();
Text area = GetHintRegion(Location(magicLocation[0])->GetParentRegionKey())->GetHint().GetText();
auto ctx = Rando::Context::GetInstance();
//Get the location of a magic upgrade
auto magicLocation = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc){return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_PROGRESSIVE_MAGIC_METER;});
sariaHintLoc = Rando::StaticData::GetLocation(magicLocation[0])->GetName();
Text area = GetHintRegion(ctx->GetItemLocation(magicLocation[0])->GetParentRegionKey())->GetHint().GetText();
Text temp1 = Text{
"Did you feel the %gsurge of magic%w recently? A mysterious bird told me it came from %r",
"As-tu récemment ressenti une vague de %gpuissance magique%w? Un mystérieux hibou m'a dit qu'elle provenait du %r",
@@ -935,7 +976,7 @@ void CreateWarpSongTexts() {
}
void CreateAllHints() {
auto ctx = Rando::Context::GetInstance();
SPDLOG_DEBUG("\nNOW CREATING HINTS\n");
const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value<uint8_t>()];
@@ -944,24 +985,26 @@ void CreateAllHints() {
// Add 'always' location hints
if (hintSetting.distTable[static_cast<int>(HINT_TYPE_ALWAYS)].copies > 0) {
// Only filter locations that had a random item placed at them (e.g. don't get cow locations if shuffle cows is off)
auto alwaysHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){
return ((Location(loc)->GetHint().GetType() == HintCategory::Always) ||
// If we have Rainbow Bridge set to Greg, add a hint for where Greg is
(Bridge.Is(RAINBOWBRIDGE_GREG) && !GregHintText && Location(loc)->GetPlacedItemKey() == GREG_RUPEE)) &&
Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt());
});
// Only filter locations that had a random item placed at them (e.g. don't get cow locations if shuffle cows is
// off)
auto alwaysHintLocations = FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return ((Rando::StaticData::GetLocation(loc)->GetHint()->GetType() == HintCategory::Always) ||
// If we have Rainbow Bridge set to Greg, add a hint for where Greg is
(Bridge.Is(RAINBOWBRIDGE_GREG) && !GregHintText &&
ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_GREG_RUPEE)) &&
ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsHintedAt());
});
for (auto& hint : conditionalAlwaysHints) {
uint32_t loc = hint.first;
if (hint.second() && Location(loc)->IsHintable() && !Location(loc)->IsHintedAt()) {
alwaysHintLocations.push_back(loc);
}
}
for (auto& hint : conditionalAlwaysHints) {
RandomizerCheck loc = hint.first;
if (hint.second() && ctx->GetItemLocation(loc)->IsHintable() && !ctx->GetItemLocation(loc)->IsHintedAt()) {
alwaysHintLocations.push_back(loc);
}
}
for (uint32_t location : alwaysHintLocations) {
CreateLocationHint({location});
}
for (RandomizerCheck location : alwaysHintLocations) {
CreateLocationHint({ location });
}
}
//Add 'trial' location hints
@@ -987,8 +1030,8 @@ void CreateAllHints() {
"Water Temple", "Spirit Temple", "Shadow Temple", "Bottom of the Well", "Ice Cavern"};
//Get list of all barren dungeons
std::vector<std::string> barrenDungeons;
for (uint32_t barrenLocation : barrenLocations) {
std::string barrenRegion = GetHintRegion(Location(barrenLocation)->GetParentRegionKey())->scene;
for (RandomizerCheck barrenLocation : barrenLocations) {
std::string barrenRegion = GetHintRegion(ctx->GetItemLocation(barrenLocation)->GetParentRegionKey())->scene;
bool isDungeon = std::find(dungeonNames.begin(), dungeonNames.end(), barrenRegion) != dungeonNames.end();
//If it hasn't already been added to the list and is a dungeon, add to list
if (isDungeon && std::find(barrenDungeons.begin(), barrenDungeons.end(), barrenRegion) == barrenDungeons.end()) {
@@ -1002,8 +1045,8 @@ void CreateAllHints() {
//Get list of all woth dungeons
std::vector<std::string> wothDungeons;
for (uint32_t wothLocation : wothLocations) {
std::string wothRegion = GetHintRegion(Location(wothLocation)->GetParentRegionKey())->scene;
for (RandomizerCheck wothLocation : ctx->wothLocations) {
std::string wothRegion = GetHintRegion(ctx->GetItemLocation(wothLocation)->GetParentRegionKey())->scene;
bool isDungeon = std::find(dungeonNames.begin(), dungeonNames.end(), wothRegion) != dungeonNames.end();
//If it hasn't already been added to the list and is a dungeon, add to list
if (isDungeon && std::find(wothDungeons.begin(), wothDungeons.end(), wothRegion) == wothDungeons.end()) {
@@ -1028,58 +1071,78 @@ void CreateAllHints() {
}
//while there are still gossip stones remaining
while (FilterFromPool(gossipStoneLocations, [](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == NONE;}).size() != 0) {
//TODO: fixed hint types
while (FilterFromPool(Rando::StaticData::gossipStoneLocations, [ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_NONE;
}).size() != 0) {
// TODO: fixed hint types
if (remainingHintTypes.empty()) {
break;
}
if (remainingHintTypes.empty()) {
break;
}
//get a random hint type from the remaining hints
HintType type = RandomElement(remainingHintTypes, true);
// get a random hint type from the remaining hints
HintType type = RandomElement(remainingHintTypes, true);
SPDLOG_DEBUG("Attempting to make hint of type: ");
SPDLOG_DEBUG(hintTypeNames.find(type)->second);
SPDLOG_DEBUG("\n");
SPDLOG_DEBUG("Attempting to make hint of type: ");
SPDLOG_DEBUG(hintTypeNames.find(type)->second);
SPDLOG_DEBUG("\n");
//create the appropriate hint for the type
if (type == HINT_TYPE_WOTH) {
CreateWothHint(&remainingDungeonWothHints);
// create the appropriate hint for the type
if (type == HINT_TYPE_WOTH) {
CreateWothHint(&remainingDungeonWothHints);
} else if (type == HINT_TYPE_BARREN) {
CreateBarrenHint(&remainingDungeonBarrenHints, barrenLocations);
} else if (type == HINT_TYPE_BARREN) {
CreateBarrenHint(&remainingDungeonBarrenHints, barrenLocations);
} else if (type == HINT_TYPE_SOMETIMES){
std::vector<uint32_t> sometimesHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->GetHint().GetType() == HintCategory::Sometimes && Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt());});
CreateLocationHint(sometimesHintLocations);
} else if (type == HINT_TYPE_SOMETIMES) {
std::vector<RandomizerCheck> sometimesHintLocations =
FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return ctx->GetHint(ctx->GetItemLocation(loc)->GetHintKey())->GetHintType() == HINT_TYPE_SOMETIMES &&
ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsHintedAt());
});
CreateLocationHint(sometimesHintLocations);
} else if (type == HINT_TYPE_RANDOM) {
CreateRandomLocationHint();
} else if (type == HINT_TYPE_RANDOM) {
CreateRandomLocationHint();
} else if (type == HINT_TYPE_ITEM) {
CreateGoodItemHint();
} else if (type == HINT_TYPE_ITEM) {
CreateGoodItemHint();
} else if (type == HINT_TYPE_SONG){
std::vector<uint32_t> songHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->IsCategory(Category::cSong) && Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt());});
CreateLocationHint(songHintLocations);
} else if (type == HINT_TYPE_SONG) {
std::vector<RandomizerCheck> songHintLocations =
FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return Rando::StaticData::GetLocation(loc)->IsCategory(Category::cSong) &&
ctx->GetItemLocation(loc)->IsHintable() && !(ctx->GetItemLocation(loc)->IsHintedAt());
});
CreateLocationHint(songHintLocations);
} else if (type == HINT_TYPE_OVERWORLD){
std::vector<uint32_t> overworldHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->IsOverworld() && Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt());});
CreateLocationHint(overworldHintLocations);
} else if (type == HINT_TYPE_OVERWORLD) {
std::vector<RandomizerCheck> overworldHintLocations =
FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return Rando::StaticData::GetLocation(loc)->IsOverworld() && ctx->GetItemLocation(loc)->IsHintable() &&
!(ctx->GetItemLocation(loc)->IsHintedAt());
});
CreateLocationHint(overworldHintLocations);
} else if (type == HINT_TYPE_DUNGEON){
std::vector<uint32_t> dungeonHintLocations = FilterFromPool(allLocations, [](const uint32_t loc){return Location(loc)->IsDungeon() && Location(loc)->IsHintable() && !(Location(loc)->IsHintedAt());});
CreateLocationHint(dungeonHintLocations);
} else if (type == HINT_TYPE_DUNGEON) {
std::vector<RandomizerCheck> dungeonHintLocations =
FilterFromPool(ctx->allLocations, [ctx](const RandomizerCheck loc) {
return Rando::StaticData::GetLocation(loc)->IsDungeon() && ctx->GetItemLocation(loc)->IsHintable() &&
!(ctx->GetItemLocation(loc)->IsHintedAt());
});
CreateLocationHint(dungeonHintLocations);
} else if (type == HINT_TYPE_JUNK) {
CreateJunkHint();
}
} else if (type == HINT_TYPE_JUNK) {
CreateJunkHint();
}
}
//If any gossip stones failed to have a hint placed on them for some reason, place a junk hint as a failsafe.
for (uint32_t gossipStone : FilterFromPool(gossipStoneLocations, [](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == NONE;})) {
const HintText junkHint = RandomElement(GetHintCategory(HintCategory::Junk));
AddHint(junkHint.GetText(), gossipStone, {QM_PINK});
for (RandomizerCheck gossipStone : FilterFromPool(Rando::StaticData::gossipStoneLocations, [ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == RG_NONE;
})) {
const HintText junkHint = RandomElement(GetHintCategory(HintCategory::Junk));
AddHint(junkHint.GetText(), gossipStone, { QM_PINK });
}
//Getting gossip stone locations temporarily sets one location to not be reachable.

View File

@@ -4,10 +4,10 @@
#include <string>
#include <vector>
#include "keys.hpp"
#include "text.hpp"
#include "random.hpp"
#include "settings.hpp"
#include "dungeon.hpp"
#include <functional>
struct HintDistributionSetting {
@@ -193,14 +193,14 @@ private:
HintCategory type;
};
using ConditionalAlwaysHint = std::pair<uint32_t, std::function<bool()>>;
using ConditionalAlwaysHint = std::pair<RandomizerCheck, std::function<bool()>>;
//10 dungeons as GTG and GC are excluded
extern std::array<DungeonInfo, 10> dungeonInfoData;
extern std::array<ConditionalAlwaysHint, 9> conditionalAlwaysHints;
extern uint32_t GetHintRegionHintKey(const uint32_t area);
extern RandomizerHintTextKey GetHintRegionHintKey(const RandomizerRegion area);
extern void CreateAllHints();
extern void CreateMerchantsHints();
extern void CreateWarpSongTexts();

View File

@@ -1,86 +0,0 @@
#include "item.hpp"
#include <array>
#include "item_location.hpp"
#include "logic.hpp"
#include "random.hpp"
#include "item_pool.hpp"
#include "settings.hpp"
#include "z64item.h"
Item::Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int getItemId_, bool advancement_, bool* logicVar_, uint32_t hintKey_,
uint16_t price_)
: randomizerGet(randomizerGet_),
name(std::move(name_)),
type(type_),
getItemId(getItemId_),
advancement(advancement_),
logicVar(logicVar_),
hintKey(hintKey_),
price(price_) {}
Item::Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int getItemId_, bool advancement_, uint8_t* logicVar_, uint32_t hintKey_,
uint16_t price_)
: randomizerGet(randomizerGet_),
name(std::move(name_)),
type(type_),
getItemId(getItemId_),
advancement(advancement_),
logicVar(logicVar_),
hintKey(hintKey_),
price(price_) {}
Item::~Item() = default;
void Item::ApplyEffect() {
//If this is a key ring, logically add as many keys as we could need
if (FOREST_TEMPLE_KEY_RING <= hintKey && hintKey <= GANONS_CASTLE_KEY_RING) {
*std::get<uint8_t*>(logicVar) += 10;
}
else {
if (std::holds_alternative<bool*>(logicVar)) {
*std::get<bool*>(logicVar) = true;
} else {
*std::get<uint8_t*>(logicVar) += 1;
}
}
Logic::UpdateHelpers();
}
void Item::UndoEffect() {
if (FOREST_TEMPLE_KEY_RING <= hintKey && hintKey <= GANONS_CASTLE_KEY_RING) {
*std::get<uint8_t*>(logicVar) -= 10;
}
else {
if (std::holds_alternative<bool*>(logicVar)) {
*std::get<bool*>(logicVar) = false;
} else {
*std::get<uint8_t*>(logicVar) -= 1;
}
}
Logic::UpdateHelpers();
}
ItemOverride_Value Item::Value() const {
ItemOverride_Value val;
val.all = 0;
val.itemId = getItemId;
if (getItemId == GI_ICE_TRAP) {
val.looksLikeItemId = RandomElement(IceTrapModels);
}
if (getItemId >= 0x95 && getItemId <= 0x9A) { //Boss keys
val.looksLikeItemId = GI_KEY_BOSS;
}
if (getItemId >= 0xAF && getItemId <= 0xB7) { //Small keys
val.looksLikeItemId = GI_KEY_SMALL;
}
if (type == ITEMTYPE_SHOP) {
// With the current shopsanity implementation, we need a way to detect
// regular shop items. This method should have no unintended side effects
// unless there was a multiworld with 256 players... so, it should be fine.
val.player = 0xFF;
}
return val;
}

View File

@@ -1,156 +0,0 @@
#pragma once
#include <string>
#include <variant>
#include "keys.hpp"
#include "hint_list.hpp"
#include "settings.hpp"
#include "../randomizerTypes.h"
union ItemOverride_Value;
enum ItemType {
ITEMTYPE_ITEM,
ITEMTYPE_MAP,
ITEMTYPE_COMPASS,
ITEMTYPE_BOSSKEY,
ITEMTYPE_SMALLKEY,
ITEMTYPE_TOKEN,
ITEMTYPE_FORTRESS_SMALLKEY,
ITEMTYPE_EVENT,
ITEMTYPE_DROP,
ITEMTYPE_REFILL,
ITEMTYPE_SONG,
ITEMTYPE_SHOP,
ITEMTYPE_DUNGEONREWARD
};
class Item {
public:
Item() = default;
Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int getItemId_, bool advancement_, bool* logicVar_, uint32_t hintKey_,
uint16_t price_ = 0);
Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int getItemId_, bool advancement_, uint8_t* logicVar_, uint32_t hintKey_,
uint16_t price_ = 0);
~Item();
void ApplyEffect();
void UndoEffect();
ItemOverride_Value Value() const;
const Text& GetName() const {
return name;
}
bool IsAdvancement() const {
return advancement;
}
int GetItemID() const {
return getItemId;
}
ItemType GetItemType() const {
return type;
}
RandomizerGet GetRandomizerGet() {
return randomizerGet;
}
uint16_t GetPrice() const {
return price;
}
void SetPrice(uint16_t price_) {
price = price_;
}
void SetAsPlaythrough() {
playthrough = true;
}
bool IsPlaythrough() const {
return playthrough;
}
bool IsBottleItem() const {
return getItemId == 0x0F || //Empty Bottle
getItemId == 0X14 || //Bottle with Milk
(getItemId >= 0x8C && getItemId <= 0x94); //Rest of bottled contents
}
bool IsMajorItem() const {
using namespace Settings;
if (type == ITEMTYPE_TOKEN) {
return Bridge.Is(RAINBOWBRIDGE_TOKENS) || LACSCondition == LACSCONDITION_TOKENS;
}
if (type == ITEMTYPE_DROP || type == ITEMTYPE_EVENT || type == ITEMTYPE_SHOP || type == ITEMTYPE_MAP || type == ITEMTYPE_COMPASS) {
return false;
}
if (type == ITEMTYPE_DUNGEONREWARD && (ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON))) {
return false;
}
if ((randomizerGet == RG_BOMBCHU_5 || randomizerGet == RG_BOMBCHU_10 || randomizerGet == RG_BOMBCHU_20) && !BombchusInLogic) {
return false;
}
if (hintKey == HEART_CONTAINER || hintKey == PIECE_OF_HEART || hintKey == TREASURE_GAME_HEART) {
return false;
}
if (type == ITEMTYPE_SMALLKEY && (Keysanity.Is(KEYSANITY_VANILLA) || Keysanity.Is(KEYSANITY_OWN_DUNGEON))) {
return false;
}
if (type == ITEMTYPE_FORTRESS_SMALLKEY && GerudoKeys.Is(GERUDOKEYS_VANILLA)) {
return false;
}
if ((type == ITEMTYPE_BOSSKEY && getItemId != 0xAD) && (BossKeysanity.Is(BOSSKEYSANITY_VANILLA) || BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON))) {
return false;
}
//Ganons Castle Boss Key
if (getItemId == 0xAD && (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA) || GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON))) {
return false;
}
if (randomizerGet == RG_GREG_RUPEE) {
return Bridge.Is(RAINBOWBRIDGE_GREG);
}
return IsAdvancement();
}
uint32_t GetHintKey() const {
return hintKey;
}
const HintText& GetHint() const {
return Hint(hintKey);
}
bool operator== (const Item& right) const {
return type == right.GetItemType() && getItemId == right.GetItemID();
}
bool operator!= (const Item& right) const {
return !operator==(right);
}
private:
RandomizerGet randomizerGet;
Text name;
ItemType type;
int getItemId;
bool advancement;
std::variant<bool*, uint8_t*> logicVar;
uint32_t hintKey;
uint16_t price;
bool playthrough = false;
};

View File

@@ -320,3 +320,4 @@ void NewItem(const uint32_t itemKey, const Item item) {
std::array<Item, KEY_ENUM_MAX>* GetFullItemTable_() {
return &itemTable;
}

View File

@@ -1,10 +0,0 @@
#pragma once
#include "item.hpp"
#include "keys.hpp"
void ItemTable_Init();
Item& ItemTable(uint32_t itemKey);
Item& ItemFromGIID(int giid);
void NewItem(uint32_t itemKey, Item item);
std::array<Item, KEY_ENUM_MAX>* GetFullItemTable_();

File diff suppressed because it is too large Load Diff

View File

@@ -1,529 +0,0 @@
#pragma once
#include <algorithm>
#include <array>
#include <cstdio>
#include <functional>
#include <set>
#include <string>
#include <vector>
#include "spoiler_log.hpp"
#include "item_list.hpp"
#include "../randomizerTypes.h"
enum ItemOverride_Type {
OVR_BASE_ITEM = 0,
OVR_CHEST = 1,
OVR_COLLECTABLE = 2,
OVR_SKULL = 3,
OVR_GROTTO_SCRUB = 4,
OVR_DELAYED = 5,
OVR_TEMPLE = 6,
};
typedef enum {
DUNGEON_DEKU_TREE = 0,
DUNGEON_DODONGOS_CAVERN,
DUNGEON_JABUJABUS_BELLY,
DUNGEON_FOREST_TEMPLE,
DUNGEON_FIRE_TEMPLE,
DUNGEON_WATER_TEMPLE,
DUNGEON_SPIRIT_TEMPLE,
DUNGEON_SHADOW_TEMPLE,
DUNGEON_BOTTOM_OF_THE_WELL,
DUNGEON_ICE_CAVERN,
DUNGEON_GANONS_CASTLE_SECOND_PART,
DUNGEON_GERUDO_TRAINING_GROUNDS,
DUNGEON_GERUDO_FORTRESS,
DUNGEON_GANONS_CASTLE_FIRST_PART,
DUNGEON_GANONS_CASTLE_FLOOR_BENEATH_BOSS_CHAMBER,
DUNGEON_GANONS_CASTLE_CRUMBLING,
DUNGEON_TREASURE_CHEST_SHOP,
DUNGEON_DEKU_TREE_BOSS_ROOM,
DUNGEON_DODONGOS_CAVERN_BOSS_ROOM,
DUNGEON_JABUJABUS_BELLY_BOSS_ROOM,
} DungeonId;
typedef union ItemOverride_Key {
uint32_t all;
struct {
char pad_;
uint8_t scene;
uint8_t type;
};
} ItemOverride_Key;
typedef union ItemOverride_Value {
uint32_t all;
struct {
uint16_t itemId;
uint8_t player;
uint8_t looksLikeItemId;
};
} ItemOverride_Value;
typedef struct ItemOverride {
ItemOverride_Key key;
ItemOverride_Value value;
} ItemOverride;
class Entrance;
enum class ItemLocationType {
Base,
Chest,
Collectable,
GSToken,
GrottoScrub,
Delayed,
TempleReward,
HintStone,
OtherHint,
};
class SpoilerCollectionCheck {
public:
SpoilerCollectionCheckType type = SpoilerCollectionCheckType::SPOILER_CHK_NONE;
uint8_t scene = 0;
uint8_t flag = 0;
SpoilerCollectionCheck() {}
SpoilerCollectionCheck(SpoilerCollectionCheckType type_, uint8_t scene_, uint8_t flag_) : type(type_), scene(scene_), flag(flag_) {}
static auto None() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_NONE, 0x00, 0x00);
}
static auto AlwaysCollected() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_ALWAYS_COLLECTED, 0x00, 0x00);
}
static auto ItemGetInf(uint8_t slot) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF, 0x00, slot);
}
static auto EventChkInf(uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF, 0xFF, flag);
}
static auto InfTable(uint8_t offset, uint8_t bit) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_INF_TABLE, offset, bit);
}
static auto Collectable(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE, scene, flag);
}
static auto Chest(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_CHEST, scene, flag);
}
static auto Cow() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COW, 0x00, 0x00);
}
static auto Fishing() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MINIGAME, 0x00, 0x00);
}
static auto Scrub() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_SCRUB, 0x00, 0x00);
}
static auto GerudoToken() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, 0x00, 0x00);
}
static auto BigPoePoints() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_POE_POINTS, 0x00, 0x00);
}
static auto Gravedigger(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GRAVEDIGGER, scene, flag);
}
static auto ShopItem() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM, 0x00, 0x00);
}
static auto MagicBeans() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MAGIC_BEANS, 0x00, 0x00);
}
static auto Merchant() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT, 0x00, 0x00);
}
static auto RandomizerInf() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF, 0x00, 0x00);
}
};
class ItemLocation {
public:
ItemLocation() = default;
ItemLocation(RandomizerCheck rc_, uint8_t scene_, ItemLocationType type_, std::string name_, uint32_t hintKey_, uint32_t vanillaItem_, std::vector<Category> categories_, uint16_t price_ = 0, SpoilerCollectionCheck collectionCheck_ = SpoilerCollectionCheck(), SpoilerCollectionCheckGroup collectionCheckGroup_ = SpoilerCollectionCheckGroup::GROUP_NO_GROUP)
: rc(rc_), scene(scene_), type(type_), name(std::move(name_)), hintKey(hintKey_), vanillaItem(vanillaItem_), categories(std::move(categories_)), price(price_), collectionCheck(collectionCheck_), collectionCheckGroup(collectionCheckGroup_) {}
ItemOverride_Key Key() const {
ItemOverride_Key key;
key.all = 0;
key.scene = scene;
key.type = static_cast<uint8_t>(type); //TODO make sure these match up
return key;
}
RandomizerCheck GetRandomizerCheck() const {
return rc;
}
SpoilerCollectionCheck GetCollectionCheck() const {
return collectionCheck;
}
SpoilerCollectionCheckGroup GetCollectionCheckGroup() const {
return collectionCheckGroup;
}
uint8_t GetScene() const {
return scene;
}
bool IsAddedToPool() const {
return addedToPool;
}
void AddToPool() {
addedToPool = true;
}
uint32_t GetHintKey() const {
return hintKey;
}
void RemoveFromPool() {
addedToPool = false;
}
const std::string& GetName() const {
return name;
}
const Text& GetPlacedItemName() const {
return ItemTable(placedItem).GetName();
}
const Item& GetPlacedItem() const {
return ItemTable(placedItem);
}
uint32_t GetPlacedItemKey() const {
return placedItem;
}
uint32_t GetPlaceduint32_t() const {
return placedItem;
}
void SetPlacedItem(const uint32_t item) {
placedItem = item;
SetPrice(ItemTable(placedItem).GetPrice());
}
//Saves an item to be set as placedItem later
void SetDelayedItem(const uint32_t item) {
delayedItem = item;
}
//Place the vanilla item in this location
void PlaceVanillaItem() {
placedItem = vanillaItem;
}
void ApplyPlacedItemEffect() {
ItemTable(placedItem).ApplyEffect();
}
//Set placedItem as item saved in SetDelayedItem
void SaveDelayedItem() {
placedItem = delayedItem;
delayedItem = NONE;
}
uint16_t GetPrice() const {
if (ItemTable(placedItem).GetItemType() == ITEMTYPE_SHOP) {
return ItemTable(placedItem).GetPrice();
}
return price;
}
void SetPrice(uint16_t price_) {
//don't override price if the price was set for shopsanity/scrubsanity
if (hasShopsanityPrice || hasScrubsanityPrice) {
return;
}
price = price_;
}
void SetShopsanityPrice(uint16_t price_) {
price = price_;
hasShopsanityPrice = true;
}
void SetScrubsanityPrice(uint16_t price_) {
price = price_;
hasScrubsanityPrice = true;
}
bool HasShopsanityPrice() const {
return hasShopsanityPrice;
}
bool HasScrubsanityPrice() const {
return hasScrubsanityPrice;
}
bool IsExcluded() const {
return excludedOption.Value<bool>();
}
bool IsCategory(Category category) const {
return std::any_of(categories.begin(), categories.end(),
[category](auto entry) { return entry == category; });
}
bool IsDungeon() const {
return (type != ItemLocationType::GSToken && (scene < 0x0E || (scene > 0x10 && scene < 0x1A))) || (type == ItemLocationType::GSToken && scene < 0x0A);
}
bool IsOverworld() const {
return !IsDungeon();
}
bool IsShop() const {
return (scene >= 0x2C && scene <= 0x32);
}
Option * GetExcludedOption() {
return &excludedOption;
}
uint32_t Getuint32_t() const {
return hintKey;
}
const HintText& GetHint() const {
return Hint(hintKey);
}
bool IsHintedAt() const {
return hintedAt;
}
void SetAsHinted() {
hintedAt = true;
}
bool IsHidden() const {
return hidden;
}
void SetHidden(const bool hidden_) {
hidden = hidden_;
}
bool IsHintable() const {
return isHintable;
}
void SetHintedLocation(uint32_t location) {
hintedLocation = location;
}
uint32_t GetHintedLocation() {
return hintedLocation;
}
void SetHintType(HintType type) {
hintType = type;
}
HintType GetHintType() {
return hintType;
}
void SetHintedRegion (std::string region) {
hintedRegion = region;
}
std::string GetHintedRegion() {
return hintedRegion;
}
void SetAsHintable() {
isHintable = true;
}
void SetParentRegion(uint32_t region) {
parentRegion = region;
}
uint32_t GetParentRegionKey() const {
return parentRegion;
}
void AddExcludeOption() {
//add option to forbid any location from progress items
if (name.length() < 23) {
excludedOption = Option::Bool(name, {"Include", "Exclude"});
} else {
//insert a newline character if the text is too long for one row
size_t lastSpace = name.rfind(' ', 23);
std::string settingText = name;
settingText.replace(lastSpace, 1, "\n ");
excludedOption = Option::Bool(settingText, {"Include", "Exclude"});
}
// RANDOTODO: this without string compares and loops
bool alreadyAdded = false;
for(const Option* location : Settings::excludeLocationsOptionsVector[collectionCheckGroup]) {
if (location->GetName() == excludedOption.GetName()) {
alreadyAdded = true;
}
}
if (!alreadyAdded) {
Settings::excludeLocationsOptionsVector[collectionCheckGroup].push_back(&excludedOption);
}
}
static auto Base(RandomizerCheck rc, uint8_t scene, std::string&& name, const uint32_t hintKey, const uint32_t vanillaItem, std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP) {
return ItemLocation{rc, scene, ItemLocationType::Base, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
}
static auto Chest(RandomizerCheck rc, uint8_t scene, uint8_t flag, std::string&& name, const uint32_t hintKey, const uint32_t vanillaItem, std::vector<Category>&& categories, SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP) {
return ItemLocation{rc, scene, ItemLocationType::Chest, std::move(name), hintKey, vanillaItem, std::move(categories), 0, SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_CHEST, scene, flag), collectionCheckGroup};
}
static auto Chest(RandomizerCheck rc, uint8_t scene, std::string&& name, const uint32_t hintKey, const uint32_t vanillaItem, std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck, SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP) {
return ItemLocation{rc, scene, ItemLocationType::Chest, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
}
static auto Collectable(RandomizerCheck rc, uint8_t scene, uint8_t flag, std::string&& name, const uint32_t hintKey, const uint32_t vanillaItem, std::vector<Category>&& categories, SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP) {
return ItemLocation{rc, scene, ItemLocationType::Collectable, std::move(name), hintKey, vanillaItem, std::move(categories), 0, SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE, scene, flag), collectionCheckGroup};
}
static auto Collectable(RandomizerCheck rc, uint8_t scene, std::string&& name, const uint32_t hintKey, const uint32_t vanillaItem, std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck, SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP) {
return ItemLocation{rc, scene, ItemLocationType::Collectable, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
}
static auto GSToken(RandomizerCheck rc, uint8_t scene, uint8_t flag, std::string&& name, const uint32_t hintKey, std::vector<Category>&& categories, SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP) {
return ItemLocation{rc, scene, ItemLocationType::GSToken, std::move(name), hintKey, GOLD_SKULLTULA_TOKEN, std::move(categories), 0, SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA, scene, flag), collectionCheckGroup};
}
static auto GrottoScrub(RandomizerCheck rc, uint8_t scene, std::string&& name, const uint32_t hintKey, const uint32_t vanillaItem, std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP) {
return ItemLocation{rc, scene, ItemLocationType::GrottoScrub, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
}
static auto Delayed(RandomizerCheck rc, uint8_t scene, std::string&& name, const uint32_t hintKey, const uint32_t vanillaItem, std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP) {
return ItemLocation{rc, scene, ItemLocationType::Delayed, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
}
static auto Reward(RandomizerCheck rc, uint8_t scene, std::string&& name, const uint32_t hintKey, const uint32_t vanillaItem, std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP) {
return ItemLocation{rc, scene, ItemLocationType::TempleReward, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
}
static auto OtherHint(RandomizerCheck rc, std::string&& name) {
return ItemLocation{rc, 0, ItemLocationType::OtherHint, std::move(name), NONE, NONE, {}};
}
static auto HintStone(RandomizerCheck rc, std::string&& name) {
return ItemLocation{rc, 0, ItemLocationType::HintStone, std::move(name), NONE, NONE, {}};
}
void ResetVariables() {
checked = false;
addedToPool = false;
placedItem = NONE;
delayedItem = NONE;
hintedAt = false;
isHintable = false;
price = 0;
hasShopsanityPrice = false;
hasScrubsanityPrice = false;
hidden = false;
}
private:
RandomizerCheck rc;
uint8_t scene;
ItemLocationType type;
bool checked = false;
std::string name;
uint32_t hintKey = NONE;
uint32_t vanillaItem = NONE;
bool hintedAt = false;
std::vector<Category> categories;
bool addedToPool = false;
uint32_t placedItem = NONE;
uint32_t hintedLocation = NONE;
HintType hintType;
std::string hintedRegion;
uint32_t delayedItem = NONE;
Option excludedOption = Option::Bool(name, {"Include", "Exclude"});
uint16_t price = 0;
SpoilerCollectionCheck collectionCheck;
SpoilerCollectionCheckGroup collectionCheckGroup;
bool isHintable = false;
uint32_t parentRegion = NONE;
bool hasShopsanityPrice = false;
bool hasScrubsanityPrice = false;
bool hidden = false;
};
class ItemOverride_Compare {
public:
bool operator()(ItemOverride lhs, ItemOverride rhs) const {
return lhs.key.all < rhs.key.all;
}
};
void LocationTable_Init();
ItemLocation* Location(uint32_t locKey);
ItemLocation* Location(RandomizerCheck rc);
extern std::vector<std::vector<uint32_t>> ShopLocationLists;
extern std::vector<uint32_t> ScrubLocations;
extern std::vector<uint32_t> gossipStoneLocations;
extern std::vector<uint32_t> dungeonRewardLocations;
extern std::vector<uint32_t> overworldLocations;
extern std::vector<uint32_t> allLocations;
extern std::vector<uint32_t> everyPossibleLocation;
//set of overrides to write to the patch
extern std::set<ItemOverride, ItemOverride_Compare> overrides;
extern std::unordered_map<RandomizerCheck, uint8_t> iceTrapModels;
extern std::vector<std::vector<uint32_t>> playthroughLocations;
extern std::vector<uint32_t> wothLocations;
extern bool playthroughBeatable;
extern bool allLocationsReachable;
extern bool showItemProgress;
extern uint16_t itemsPlaced;
void GenerateLocationPool();
void PlaceItemInLocation(uint32_t loc, uint32_t item, bool applyEffectImmediately = false, bool setHidden = false);
std::vector<uint32_t> GetLocations(const std::vector<uint32_t>& locationPool, Category categoryInclude,
Category categoryExclude = Category::cNull);
void LocationReset();
void ItemReset();
void HintReset();
void AddExcludedOptions();
void CreateItemOverrides();

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,17 @@
#pragma once
#include "keys.hpp"
#include <cstddef>
#include <vector>
#include <stdint.h>
#include "../randomizerTypes.h"
class ItemLocation;
void AddItemToPool(std::vector<uint32_t>& pool, const uint32_t item, size_t count = 1);
uint32_t GetJunkItem();
void PlaceJunkInExcludedLocation(const uint32_t il);
void AddItemToPool(std::vector<RandomizerGet>& pool, const RandomizerGet item, size_t count = 1);
RandomizerGet GetJunkItem();
void PlaceJunkInExcludedLocation(const RandomizerCheck il);
void GenerateItemPool();
void AddJunk();
extern std::vector<uint32_t> ItemPool;
extern std::vector<RandomizerGet> ItemPool;
extern std::vector<uint8_t> IceTrapModels;

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
#include "location_access.hpp"
#include "dungeon.hpp"
#include "item_list.hpp"
#include "item_location.hpp"
#include "../static_data.h"
#include "../context.h"
#include "item_pool.hpp"
#include "logic.hpp"
#include "settings.hpp"
@@ -19,7 +19,7 @@ using namespace Settings;
//generic grotto event list
std::vector<EventAccess> grottoEvents = {
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || (CanUse(STICKS));}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || (CanUse(RG_STICKS));}}),
EventAccess(&BugShrub, {[]{return CanCutShrubs;}}),
EventAccess(&LoneFish, {[]{return true;}}),
};
@@ -41,7 +41,7 @@ bool LocationAccess::CheckConditionAtAgeTime(bool& age, bool& time) const {
bool LocationAccess::ConditionsMet() const {
Area* parentRegion = AreaTable(Location(location)->GetParentRegionKey());
Area* parentRegion = AreaTable(Rando::Context::GetInstance()->GetItemLocation(location)->GetParentRegionKey());
bool conditionsMet = false;
if ((parentRegion->childDay && CheckConditionAtAgeTime(IsChild, AtDay)) ||
@@ -55,37 +55,39 @@ bool LocationAccess::ConditionsMet() const {
}
bool LocationAccess::CanBuy() const {
auto ctx = Rando::Context::GetInstance();
//Not a shop location, don't need to check if buyable
if (!(Location(location)->IsCategory(Category::cShop))) {
if (!(Rando::StaticData::GetLocation(location)->IsCategory(Category::cShop))) {
return true;
}
//Check if wallet is large enough to buy item
bool SufficientWallet = true;
if (Location(location)->GetPrice() > 500) {
if (ctx->GetItemLocation(location)->GetPrice() > 500) {
SufficientWallet = ProgressiveWallet >= 3;
} else if (Location(location)->GetPrice() > 200) {
} else if (ctx->GetItemLocation(location)->GetPrice() > 200) {
SufficientWallet = ProgressiveWallet >= 2;
} else if (Location(location)->GetPrice() > 99) {
} else if (ctx->GetItemLocation(location)->GetPrice() > 99) {
SufficientWallet = ProgressiveWallet >= 1;
}
bool OtherCondition = true;
uint32_t placed = Location(location)->GetPlacedItemKey();
RandomizerGet placed = ctx->GetItemLocation(location)->GetPlacedRandomizerGet();
//Need bottle to buy bottle items, only logically relevant bottle items included here
if (placed == BUY_BLUE_FIRE || placed == BUY_BOTTLE_BUG || placed == BUY_FISH || placed == BUY_FAIRYS_SPIRIT) {
OtherCondition = HasBottle;
if (placed == RG_BUY_BLUE_FIRE || placed == RG_BUY_BOTTLE_BUG || placed == RG_BUY_FISH ||
placed == RG_BUY_FAIRYS_SPIRIT) {
OtherCondition = HasBottle;
}
//If bombchus in logic, need to have found chus to buy; if not just need bomb bag
else if (placed == BUY_BOMBCHU_10 || placed == BUY_BOMBCHU_20) {
OtherCondition = (!BombchusInLogic && Bombs) || (BombchusInLogic && FoundBombchus);
// If bombchus in logic, need to have found chus to buy; if not just need bomb bag
else if (placed == RG_BUY_BOMBCHU_10 || placed == RG_BUY_BOMBCHU_20) {
OtherCondition = (!BombchusInLogic && Bombs) || (BombchusInLogic && FoundBombchus);
}
return SufficientWallet && OtherCondition;
}
Area::Area() = default;
Area::Area(std::string regionName_, std::string scene_, uint32_t hintKey_,
Area::Area(std::string regionName_, std::string scene_, RandomizerHintTextKey hintKey_,
bool timePass_,
std::vector<EventAccess> events_,
std::vector<LocationAccess> locations_,
@@ -106,14 +108,14 @@ bool Area::UpdateEvents(SearchMode mode) {
if (Child()) {
childDay = true;
childNight = true;
AreaTable(ROOT)->childDay = true;
AreaTable(ROOT)->childNight = true;
AreaTable(RR_ROOT)->childDay = true;
AreaTable(RR_ROOT)->childNight = true;
}
if (Adult()) {
adultDay = true;
adultNight = true;
AreaTable(ROOT)->adultDay = true;
AreaTable(ROOT)->adultNight = true;
AreaTable(RR_ROOT)->adultDay = true;
AreaTable(RR_ROOT)->adultNight = true;
}
}
@@ -136,7 +138,7 @@ bool Area::UpdateEvents(SearchMode mode) {
return eventsUpdated;
}
void Area::AddExit(uint32_t parentKey, uint32_t newExitKey, ConditionFn condition) {
void Area::AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition) {
Entrance newExit = Entrance(newExitKey, {condition});
newExit.SetParentRegion(parentKey);
exits.push_front(newExit);
@@ -147,7 +149,7 @@ void Area::RemoveExit(Entrance* exitToRemove) {
exits.remove_if([exitToRemove](const auto exit){return &exit == exitToRemove;});
}
void Area::SetAsPrimary(uint32_t exitToBePrimary) {
void Area::SetAsPrimary(RandomizerRegion exitToBePrimary) {
for (auto& exit : exits) {
if (exit.Getuint32_t() == exitToBePrimary) {
exit.SetAsPrimary();
@@ -156,7 +158,7 @@ void Area::SetAsPrimary(uint32_t exitToBePrimary) {
}
}
Entrance* Area::GetExit(uint32_t exitToReturn) {
Entrance* Area::GetExit(RandomizerRegion exitToReturn) {
for (auto& exit : exits) {
if (exit.Getuint32_t() == exitToReturn) {
return &exit;
@@ -179,7 +181,7 @@ bool Area::AllAccountedFor() const {
}
for (const LocationAccess& loc : locations) {
if (!(Location(loc.GetLocation())->IsAddedToPool())) {
if (!(Rando::Context::GetInstance()->GetItemLocation(loc.GetLocation())->IsAddedToPool())) {
return false;
}
}
@@ -193,13 +195,13 @@ bool Area::AllAccountedFor() const {
return AllAccess();
}
bool Area::CheckAllAccess(const uint32_t exitKey) {
bool Area::CheckAllAccess(const RandomizerRegion exitKey) {
if (!AllAccess()) {
return false;
}
for (Entrance& exit : exits) {
if (exit.Getuint32_t() == exitKey) {
if (exit.GetConnectedRegionKey() == exitKey) {
return exit.CheckConditionAtAgeTime(Logic::IsChild, Logic::AtDay) &&
exit.CheckConditionAtAgeTime(Logic::IsChild, Logic::AtNight) &&
exit.CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtDay) &&
@@ -220,29 +222,29 @@ void Area::ResetVariables() {
}
}
std::array<Area, KEY_ENUM_MAX> areaTable;
std::array<Area, RR_MAX> areaTable;
bool Here(const uint32_t area, ConditionFn condition) {
bool Here(const RandomizerRegion area, ConditionFn condition) {
return areaTable[area].HereCheck(condition);
}
bool CanPlantBean(const uint32_t area) {
bool CanPlantBean(const RandomizerRegion area) {
return areaTable[area].CanPlantBeanCheck();
}
bool BothAges(const uint32_t area) {
bool BothAges(const RandomizerRegion area) {
return areaTable[area].BothAgesCheck();
}
bool ChildCanAccess(const uint32_t area) {
bool ChildCanAccess(const RandomizerRegion area) {
return areaTable[area].Child();
}
bool AdultCanAccess(const uint32_t area) {
bool AdultCanAccess(const RandomizerRegion area) {
return areaTable[area].Adult();
}
bool HasAccessTo(const uint32_t area) {
bool HasAccessTo(const RandomizerRegion area) {
return areaTable[area].HasAccess();
}
@@ -251,68 +253,68 @@ bool HasAccessTo(const uint32_t area) {
void AreaTable_Init() {
//Clear the array from any previous playthrough attempts. This is important so that
//locations which appear in both MQ and Vanilla dungeons don't get set in both areas.
areaTable.fill(Area("Invalid Area", "Invalid Area", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {}));
areaTable.fill(Area("Invalid Area", "Invalid Area", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {}));
//name, scene, hint text, events, locations, exits
areaTable[ROOT] = Area("Root", "", LINKS_POCKET, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_ROOT] = Area("Root", "", RHT_LINKS_POCKET, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LINKS_POCKET, {[]{return true;}}),
LocationAccess(TRIFORCE_COMPLETED, { [] { return CanCompleteTriforce;}}),
LocationAccess(RC_LINKS_POCKET, {[]{return true;}}),
LocationAccess(RC_TRIFORCE_COMPLETED, { [] { return CanCompleteTriforce;}}),
}, {
//Exits
Entrance(ROOT_EXITS, {[]{return true;}})
Entrance(RR_ROOT_EXITS, {[]{return true;}})
});
areaTable[ROOT_EXITS] = Area("Root Exits", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_ROOT_EXITS] = Area("Root Exits", "", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(CHILD_SPAWN, {[]{return IsChild;}}),
Entrance(ADULT_SPAWN, {[]{return IsAdult;}}),
Entrance(MINUET_OF_FOREST_WARP, {[]{return CanPlay(MinuetOfForest);}}),
Entrance(BOLERO_OF_FIRE_WARP, {[]{return CanPlay(BoleroOfFire) && CanLeaveForest;}}),
Entrance(SERENADE_OF_WATER_WARP, {[]{return CanPlay(SerenadeOfWater) && CanLeaveForest;}}),
Entrance(NOCTURNE_OF_SHADOW_WARP, {[]{return CanPlay(NocturneOfShadow) && CanLeaveForest;}}),
Entrance(REQUIEM_OF_SPIRIT_WARP, {[]{return CanPlay(RequiemOfSpirit) && CanLeaveForest;}}),
Entrance(PRELUDE_OF_LIGHT_WARP, {[]{return CanPlay(PreludeOfLight) && CanLeaveForest;}}),
Entrance(RR_CHILD_SPAWN, {[]{return IsChild;}}),
Entrance(RR_ADULT_SPAWN, {[]{return IsAdult;}}),
Entrance(RR_MINUET_OF_FOREST_WARP, {[]{return CanPlay(MinuetOfForest);}}),
Entrance(RR_BOLERO_OF_FIRE_WARP, {[]{return CanPlay(BoleroOfFire) && CanLeaveForest;}}),
Entrance(RR_SERENADE_OF_WATER_WARP, {[]{return CanPlay(SerenadeOfWater) && CanLeaveForest;}}),
Entrance(RR_NOCTURNE_OF_SHADOW_WARP, {[]{return CanPlay(NocturneOfShadow) && CanLeaveForest;}}),
Entrance(RR_REQUIEM_OF_SPIRIT_WARP, {[]{return CanPlay(RequiemOfSpirit) && CanLeaveForest;}}),
Entrance(RR_PRELUDE_OF_LIGHT_WARP, {[]{return CanPlay(PreludeOfLight) && CanLeaveForest;}}),
});
areaTable[CHILD_SPAWN] = Area("Child Spawn", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_CHILD_SPAWN] = Area("Child Spawn", "", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KF_LINKS_HOUSE, {[]{return true;}}),
Entrance(RR_KF_LINKS_HOUSE, {[]{return true;}}),
});
areaTable[ADULT_SPAWN] = Area("Adult Spawn", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_ADULT_SPAWN] = Area("Adult Spawn", "", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
Entrance(RR_TEMPLE_OF_TIME, {[]{return true;}}),
});
areaTable[MINUET_OF_FOREST_WARP] = Area("Minuet of Forest Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_MINUET_OF_FOREST_WARP] = Area("Minuet of Forest Warp", "", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
Entrance(RR_SACRED_FOREST_MEADOW, {[]{return true;}}),
});
areaTable[BOLERO_OF_FIRE_WARP] = Area("Bolero of Fire Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_BOLERO_OF_FIRE_WARP] = Area("Bolero of Fire Warp", "", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DMC_CENTRAL_LOCAL, {[]{return true;}}),
Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return true;}}),
});
areaTable[SERENADE_OF_WATER_WARP] = Area("Serenade of Water Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SERENADE_OF_WATER_WARP] = Area("Serenade of Water Warp", "", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(LAKE_HYLIA, {[]{return true;}}),
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
});
areaTable[REQUIEM_OF_SPIRIT_WARP] = Area("Requiem of Spirit Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_REQUIEM_OF_SPIRIT_WARP] = Area("Requiem of Spirit Warp", "", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}),
});
areaTable[NOCTURNE_OF_SHADOW_WARP] = Area("Nocturne of Shadow Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_NOCTURNE_OF_SHADOW_WARP] = Area("Nocturne of Shadow Warp", "", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GRAVEYARD_WARP_PAD_REGION, {[]{return true;}}),
Entrance(RR_GRAVEYARD_WARP_PAD_REGION, {[]{return true;}}),
});
areaTable[PRELUDE_OF_LIGHT_WARP] = Area("Prelude of Light Warp", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_PRELUDE_OF_LIGHT_WARP] = Area("Prelude of Light Warp", "", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
Entrance(RR_TEMPLE_OF_TIME, {[]{return true;}}),
});
// Overworld
@@ -338,13 +340,13 @@ void AreaTable_Init() {
AreaTable_Init_GanonsCastle();
//Set parent regions
for (uint32_t i = ROOT; i <= GANONS_CASTLE; i++) {
for (uint32_t i = RR_ROOT; i <= RR_GANONS_CASTLE; i++) {
for (LocationAccess& locPair : areaTable[i].locations) {
uint32_t location = locPair.GetLocation();
Location(location)->SetParentRegion(i);
RandomizerCheck location = locPair.GetLocation();
Rando::Context::GetInstance()->GetItemLocation(location)->SetParentRegion((RandomizerRegion)i);
}
for (Entrance& exit : areaTable[i].exits) {
exit.SetParentRegion(i);
exit.SetParentRegion((RandomizerRegion)i);
exit.SetName();
exit.GetConnectedRegion()->entrances.push_front(&exit);
}
@@ -361,14 +363,14 @@ void AreaTable_Init() {
namespace Areas {
const auto GetAllAreas() {
static const size_t areaCount = MARKER_AREAS_END - (MARKER_AREAS_START + 1);
static const size_t areaCount = RR_MAX - (RR_NONE + 1);
static std::array<uint32_t, areaCount> allAreas = {};
static std::array<RandomizerRegion, areaCount> allAreas = {};
static bool intialized = false;
if (!intialized) {
for (size_t i = 0; i < areaCount; i++) {
allAreas[i] = (MARKER_AREAS_START + 1) + i;
allAreas[i] = (RandomizerRegion)((RR_NONE + 1) + i);
}
intialized = true;
}
@@ -377,53 +379,53 @@ namespace Areas {
}
void AccessReset() {
for (const uint32_t area : GetAllAreas()) {
for (const RandomizerRegion area : GetAllAreas()) {
AreaTable(area)->ResetVariables();
}
if(Settings::HasNightStart) {
if(Settings::ResolvedStartingAge == AGE_CHILD) {
AreaTable(ROOT)->childNight = true;
AreaTable(RR_ROOT)->childNight = true;
} else {
AreaTable(ROOT)->adultNight = true;
AreaTable(RR_ROOT)->adultNight = true;
}
} else {
if(Settings::ResolvedStartingAge == AGE_CHILD) {
AreaTable(ROOT)->childDay = true;
AreaTable(RR_ROOT)->childDay = true;
} else {
AreaTable(ROOT)->adultDay = true;
AreaTable(RR_ROOT)->adultDay = true;
}
}
}
//Reset exits and clear items from locations
void ResetAllLocations() {
for (const uint32_t area : GetAllAreas()) {
for (const RandomizerRegion area : GetAllAreas()) {
AreaTable(area)->ResetVariables();
//Erase item from every location in this exit
for (LocationAccess& locPair : AreaTable(area)->locations) {
uint32_t location = locPair.GetLocation();
Location(location)->ResetVariables();
RandomizerCheck location = locPair.GetLocation();
Rando::Context::GetInstance()->GetItemLocation(location)->ResetVariables();
}
}
if(Settings::HasNightStart) {
if(Settings::ResolvedStartingAge == AGE_CHILD) {
AreaTable(ROOT)->childNight = true;
AreaTable(RR_ROOT)->childNight = true;
} else {
AreaTable(ROOT)->adultNight = true;
AreaTable(RR_ROOT)->adultNight = true;
}
} else {
if(Settings::ResolvedStartingAge == AGE_CHILD) {
AreaTable(ROOT)->childDay = true;
AreaTable(RR_ROOT)->childDay = true;
} else {
AreaTable(ROOT)->adultDay = true;
AreaTable(RR_ROOT)->adultDay = true;
}
}
}
bool HasTimePassAccess(uint8_t age) {
for (const uint32_t areaKey : GetAllAreas()) {
for (const RandomizerRegion areaKey : GetAllAreas()) {
auto area = AreaTable(areaKey);
if (area->timePass && ((age == AGE_CHILD && area->Child()) || (age == AGE_ADULT && area->Adult()))) {
return true;
@@ -441,7 +443,7 @@ namespace Areas {
worldGraph.open (str + ".dot");
worldGraph << "digraph {\n\tcenter=true;\n";
for (const uint32_t areaKey : GetAllAreas()) {
for (const RandomizerRegion areaKey : GetAllAreas()) {
auto area = AreaTable(areaKey);
for (auto exit : area->exits) {
if (exit.GetConnectedRegion()->regionName != "Invalid Area") {
@@ -484,8 +486,8 @@ namespace Areas {
} //namespace Areas
Area* AreaTable(const uint32_t areaKey) {
if (areaKey > KEY_ENUM_MAX) {
Area* AreaTable(const RandomizerRegion areaKey) {
if (areaKey > RR_MAX) {
printf("\x1b[1;1HERROR: AREAKEY TOO BIG");
}
return &(areaTable[areaKey]);
@@ -494,7 +496,7 @@ Area* AreaTable(const uint32_t areaKey) {
//Retrieve all the shuffable entrances of a specific type
std::vector<Entrance*> GetShuffleableEntrances(EntranceType type, bool onlyPrimary /*= true*/) {
std::vector<Entrance*> entrancesToShuffle = {};
for (uint32_t area : Areas::GetAllAreas()) {
for (RandomizerRegion area : Areas::GetAllAreas()) {
for (auto& exit: AreaTable(area)->exits) {
if ((exit.GetType() == type || type == EntranceType::All) && (exit.IsPrimary() || !onlyPrimary) && exit.GetType() != EntranceType::None) {
entrancesToShuffle.push_back(&exit);

View File

@@ -6,7 +6,6 @@
#include "logic.hpp"
#include "hint_list.hpp"
#include "keys.hpp"
#include "fill.hpp"
typedef bool (*ConditionFn)();
@@ -69,7 +68,7 @@ private:
class LocationAccess {
public:
explicit LocationAccess(uint32_t location_, std::vector<ConditionFn> conditions_met_)
explicit LocationAccess(RandomizerCheck location_, std::vector<ConditionFn> conditions_met_)
: location(location_) {
conditions_met.resize(2);
for (size_t i = 0; i < conditions_met_.size(); i++) {
@@ -96,12 +95,12 @@ public:
bool ConditionsMet() const;
uint32_t GetLocation() const {
RandomizerCheck GetLocation() const {
return location;
}
private:
uint32_t location;
protected:
RandomizerCheck location;
std::vector<ConditionFn> conditions_met;
//Makes sure shop locations are buyable
@@ -114,7 +113,7 @@ enum class EntranceType;
class Area {
public:
Area();
Area(std::string regionName_, std::string scene_, uint32_t hintKey_,
Area(std::string regionName_, std::string scene_, RandomizerHintTextKey hintKey_,
bool timePass_,
std::vector<EventAccess> events_,
std::vector<LocationAccess> locations_,
@@ -123,7 +122,7 @@ public:
std::string regionName;
std::string scene;
uint32_t hintKey;
RandomizerHintTextKey hintKey;
bool timePass;
std::vector<EventAccess> events;
std::vector<LocationAccess> locations;
@@ -143,13 +142,13 @@ public:
bool UpdateEvents(SearchMode mode);
void AddExit(uint32_t parentKey, uint32_t newExitKey, ConditionFn condition);
void AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition);
void RemoveExit(Entrance* exitToRemove);
void SetAsPrimary(uint32_t exitToBePrimary);
void SetAsPrimary(RandomizerRegion exitToBePrimary);
Entrance* GetExit(uint32_t exit);
Entrance* GetExit(RandomizerRegion exit);
bool Child() const {
return childDay || childNight;
@@ -172,7 +171,7 @@ public:
}
//Check to see if an exit can be access as both ages at both times of day
bool CheckAllAccess(uint32_t exitKey);
bool CheckAllAccess(RandomizerRegion exitKey);
const HintText& GetHint() const {
return Hint(hintKey);
@@ -218,15 +217,15 @@ public:
}
};
extern std::array<Area, KEY_ENUM_MAX> areaTable;
extern std::array<Area, RR_MAX> areaTable;
extern std::vector<EventAccess> grottoEvents;
bool Here(const AreaKey area, ConditionFn condition);
bool CanPlantBean(const AreaKey area);
bool BothAges(const AreaKey area);
bool ChildCanAccess(const AreaKey area);
bool AdultCanAccess(const AreaKey area);
bool HasAccessTo(const AreaKey area);
bool Here(const RandomizerRegion area, ConditionFn condition);
bool CanPlantBean(const RandomizerRegion area);
bool BothAges(const RandomizerRegion area);
bool ChildCanAccess(const RandomizerRegion area);
bool AdultCanAccess(const RandomizerRegion area);
bool HasAccessTo(const RandomizerRegion area);
#define DAY_NIGHT_CYCLE true
#define NO_DAY_NIGHT_CYCLE false
@@ -240,7 +239,7 @@ namespace Areas {
} //namespace Exits
void AreaTable_Init();
Area* AreaTable(const uint32_t areaKey);
Area* AreaTable(const RandomizerRegion areaKey);
std::vector<Entrance*> GetShuffleableEntrances(EntranceType type, bool onlyPrimary = true);
// Overworld

View File

@@ -10,43 +10,43 @@ void AreaTable_Init_BottomOfTheWell() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[BOTTOM_OF_THE_WELL_ENTRYWAY] = Area("Bottom of the Well Entryway", "Bottom of the Well", BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_BOTTOM_OF_THE_WELL_ENTRYWAY] = Area("Bottom of the Well Entryway", "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(BOTTOM_OF_THE_WELL_MAIN_AREA, {[]{return Dungeon::BottomOfTheWell.IsVanilla() && IsChild && (CanChildAttack || Nuts);}}),
Entrance(BOTTOM_OF_THE_WELL_MQ_PERIMETER, {[]{return Dungeon::BottomOfTheWell.IsMQ() && IsChild;}}),
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_BOTTOM_OF_THE_WELL_MAIN_AREA, {[]{return Dungeon::BottomOfTheWell.IsVanilla() && IsChild && (CanChildAttack || Nuts);}}),
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, {[]{return Dungeon::BottomOfTheWell.IsMQ() && IsChild;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::BottomOfTheWell.IsVanilla()) {
areaTable[BOTTOM_OF_THE_WELL_MAIN_AREA] = Area("Bottom of the Well Main Area", "Bottom of the Well", BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_BOTTOM_OF_THE_WELL_MAIN_AREA] = Area("Bottom of the Well Main Area", "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&StickPot, {[]{return true;}}),
EventAccess(&NutPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, {[]{return LogicLensBotw || CanUse(LENS_OF_TRUTH);}}),
LocationAccess(BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, {[]{return HasExplosives;}}),
LocationAccess(BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, {[]{return LogicLensBotw || CanUse(LENS_OF_TRUTH);}}),
LocationAccess(BOTTOM_OF_THE_WELL_COMPASS_CHEST, {[]{return LogicLensBotw || CanUse(LENS_OF_TRUTH);}}),
LocationAccess(BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, {[]{return LogicLensBotw || CanUse(LENS_OF_TRUTH);}}),
LocationAccess(BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, {[]{return (LogicLensBotw || CanUse(LENS_OF_TRUTH)) && HasExplosives;}}),
LocationAccess(BOTTOM_OF_THE_WELL_FREESTANDING_KEY, {[]{return Sticks || CanUse(DINS_FIRE);}}),
LocationAccess(BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, {[]{return CanPlay(ZeldasLullaby) && (KokiriSword || (Sticks && LogicChildDeadhand));}}),
LocationAccess(BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, {[]{return CanPlay(ZeldasLullaby) && (LogicLensBotw || CanUse(LENS_OF_TRUTH));}}),
LocationAccess(BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(BOTTOM_OF_THE_WELL_MAP_CHEST, {[]{return HasExplosives || (((SmallKeys(BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(LENS_OF_TRUTH))) || CanUse(DINS_FIRE) || (Sticks && LogicBotwBasement)) && GoronBracelet);}}),
LocationAccess(BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, {[]{return SmallKeys(BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(LENS_OF_TRUTH));}}),
LocationAccess(BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, {[]{return SmallKeys(BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(LENS_OF_TRUTH));}}),
LocationAccess(BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, {[]{return Boomerang && (LogicLensBotw || CanUse(LENS_OF_TRUTH)) && SmallKeys(BOTTOM_OF_THE_WELL, 3);}}),
LocationAccess(BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, {[]{return Boomerang && (LogicLensBotw || CanUse(LENS_OF_TRUTH)) && SmallKeys(BOTTOM_OF_THE_WELL, 3);}}),
LocationAccess(BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, {[]{return SmallKeys(BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(LENS_OF_TRUTH)) && Boomerang;}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, {[]{return HasExplosives;}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, {[]{return LogicLensBotw || CanUse(RG_LENS_OF_TRUTH);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, {[]{return (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, {[]{return Sticks || CanUse(RG_DINS_FIRE);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST, {[]{return CanPlay(ZeldasLullaby) && (KokiriSword || (Sticks && LogicChildDeadhand));}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST, {[]{return CanPlay(ZeldasLullaby) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_MAP_CHEST, {[]{return HasExplosives || (((SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH))) || CanUse(RG_DINS_FIRE) || (Sticks && LogicBotwBasement)) && GoronBracelet);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM, {[]{return Boomerang && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM, {[]{return Boomerang && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && SmallKeys(RR_BOTTOM_OF_THE_WELL, 3);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE, {[]{return SmallKeys(RR_BOTTOM_OF_THE_WELL, 3) && (LogicLensBotw || CanUse(RG_LENS_OF_TRUTH)) && Boomerang;}}),
}, {
//Exits
Entrance(BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}),
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}),
});
}
@@ -54,33 +54,33 @@ void AreaTable_Init_BottomOfTheWell() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::BottomOfTheWell.IsMQ()) {
areaTable[BOTTOM_OF_THE_WELL_MQ_PERIMETER] = Area("Bottom of the Well MQ Perimeter", "Bottom of the Well", BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER] = Area("Bottom of the Well MQ Perimeter", "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {
//Events
//EventAccess(&WallFairy, {[]{return WallFairy || Slingshot;}}),
}, {
//Locations
LocationAccess(BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, {[]{return KokiriSword || (Sticks && LogicChildDeadhand);}}),
LocationAccess(BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, {[]{return HasExplosives || (LogicBotwMQDeadHandKey && Boomerang);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST, {[]{return KokiriSword || (Sticks && LogicChildDeadhand);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY, {[]{return HasExplosives || (LogicBotwMQDeadHandKey && Boomerang);}}),
//Trick: HasExplosives || (LogicBotWMQDeadHandKey && Boomerang)
LocationAccess(BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, {[]{return CanChildAttack;}}),
LocationAccess(BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, {[]{return CanChildAttack && SmallKeys(BOTTOM_OF_THE_WELL, 2);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT, {[]{return CanChildAttack;}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM, {[]{return CanChildAttack && SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}}),
}, {
//Exits
Entrance(BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}),
Entrance(BOTTOM_OF_THE_WELL_MQ_MIDDLE, {[]{return CanPlay(ZeldasLullaby) || (LogicBotwMQPits && HasExplosives);}}),
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}),
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE, {[]{return CanPlay(ZeldasLullaby) || (LogicBotwMQPits && HasExplosives);}}),
//Trick: CanPlay(ZeldasLullaby) || (LogicBotWMQPits && HasExplosives)
});
areaTable[BOTTOM_OF_THE_WELL_MQ_MIDDLE] = Area("Bottom of the Well MQ Middle", "Bottom of the Well", BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_BOTTOM_OF_THE_WELL_MQ_MIDDLE] = Area("Bottom of the Well MQ Middle", "Bottom of the Well", RHT_BOTTOM_OF_THE_WELL, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, {[]{return true;}}),
LocationAccess(BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, {[]{return HasExplosives && SmallKeys(BOTTOM_OF_THE_WELL, 2);}}),
LocationAccess(BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, {[]{return true;}}),
LocationAccess(BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, {[]{return CanChildAttack && (LogicBotwMQPits || HasExplosives);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_MAP_CHEST, {[]{return true;}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST, {[]{return HasExplosives && SmallKeys(RR_BOTTOM_OF_THE_WELL, 2);}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY, {[]{return true;}}),
LocationAccess(RC_BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM, {[]{return CanChildAttack && (LogicBotwMQPits || HasExplosives);}}),
//Trick: CanChildAttack && (LogicBotWMQPits || HasExplosives)
}, {
//Exits
Entrance(BOTTOM_OF_THE_WELL_MQ_PERIMETER, {[]{return true;}}),
Entrance(RR_BOTTOM_OF_THE_WELL_MQ_PERIMETER, {[]{return true;}}),
});
}
}

View File

@@ -6,267 +6,267 @@ using namespace Logic;
using namespace Settings;
void AreaTable_Init_CastleTown() {
areaTable[MARKET_ENTRANCE] = Area("Market Entrance", "Market Entrance", THE_MARKET, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_MARKET_ENTRANCE] = Area("Market Entrance", "Market Entrance", RHT_THE_MARKET, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return IsAdult || AtDay;}}),
Entrance(THE_MARKET, {[]{return true;}}),
Entrance(MARKET_GUARD_HOUSE, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return IsAdult || AtDay;}}),
Entrance(RR_THE_MARKET, {[]{return true;}}),
Entrance(RR_MARKET_GUARD_HOUSE, {[]{return true;}}),
});
areaTable[THE_MARKET] = Area("Market", "Market", THE_MARKET, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_THE_MARKET] = Area("Market", "Market", RHT_THE_MARKET, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(MARKET_ENTRANCE, {[]{return true;}}),
Entrance(TOT_ENTRANCE, {[]{return true;}}),
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
Entrance(MARKET_BAZAAR, {[]{return IsChild && AtDay;}}),
Entrance(MARKET_MASK_SHOP, {[]{return IsChild && AtDay;}}),
Entrance(MARKET_SHOOTING_GALLERY, {[]{return IsChild && AtDay;}}),
Entrance(MARKET_BOMBCHU_BOWLING, {[]{return IsChild;}}),
Entrance(MARKET_TREASURE_CHEST_GAME, {[]{return IsChild && AtNight;}}),
Entrance(MARKET_POTION_SHOP, {[]{return IsChild && AtDay;}}),
Entrance(MARKET_BACK_ALLEY, {[]{return IsChild;}}),
Entrance(RR_MARKET_ENTRANCE, {[]{return true;}}),
Entrance(RR_TOT_ENTRANCE, {[]{return true;}}),
Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}),
Entrance(RR_MARKET_BAZAAR, {[]{return IsChild && AtDay;}}),
Entrance(RR_MARKET_MASK_SHOP, {[]{return IsChild && AtDay;}}),
Entrance(RR_MARKET_SHOOTING_GALLERY, {[]{return IsChild && AtDay;}}),
Entrance(RR_MARKET_BOMBCHU_BOWLING, {[]{return IsChild;}}),
Entrance(RR_MARKET_TREASURE_CHEST_GAME, {[]{return IsChild && AtNight;}}),
Entrance(RR_MARKET_POTION_SHOP, {[]{return IsChild && AtDay;}}),
Entrance(RR_MARKET_BACK_ALLEY, {[]{return IsChild;}}),
});
areaTable[MARKET_BACK_ALLEY] = Area("Market Back Alley", "Market", THE_MARKET, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_MARKET_BACK_ALLEY] = Area("Market Back Alley", "Market", RHT_THE_MARKET, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(THE_MARKET, {[]{return true;}}),
Entrance(MARKET_BOMBCHU_SHOP, {[]{return AtNight;}}),
Entrance(MARKET_DOG_LADY_HOUSE, {[]{return true;}}),
Entrance(MARKET_MAN_IN_GREEN_HOUSE, {[]{return AtNight;}}),
Entrance(RR_THE_MARKET, {[]{return true;}}),
Entrance(RR_MARKET_BOMBCHU_SHOP, {[]{return AtNight;}}),
Entrance(RR_MARKET_DOG_LADY_HOUSE, {[]{return true;}}),
Entrance(RR_MARKET_MAN_IN_GREEN_HOUSE, {[]{return AtNight;}}),
});
areaTable[TOT_ENTRANCE] = Area("ToT Entrance", "ToT Entrance", THE_MARKET, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_TOT_ENTRANCE] = Area("ToT Entrance", "ToT Entrance", RHT_THE_MARKET, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
}, {
//Locations
LocationAccess(TOT_GOSSIP_STONE_LEFT, {[]{return true;}}),
LocationAccess(TOT_GOSSIP_STONE_LEFT_CENTER, {[]{return true;}}),
LocationAccess(TOT_GOSSIP_STONE_RIGHT_CENTER, {[]{return true;}}),
LocationAccess(TOT_GOSSIP_STONE_RIGHT, {[]{return true;}}),
LocationAccess(RC_TOT_LEFT_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_TOT_LEFT_CENTER_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_TOT_RIGHT_CENTER_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_TOT_RIGHT_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(THE_MARKET, {[]{return true;}}),
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
Entrance(RR_THE_MARKET, {[]{return true;}}),
Entrance(RR_TEMPLE_OF_TIME, {[]{return true;}}),
});
areaTable[TEMPLE_OF_TIME] = Area("Temple of Time", "Temple of Time", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_TEMPLE_OF_TIME] = Area("Temple of Time", "Temple of Time", RHT_TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(TOT_LIGHT_ARROWS_CUTSCENE, {[]{return IsAdult && CanTriggerLACS;}}),
LocationAccess(RC_TOT_LIGHT_ARROWS_CUTSCENE, {[]{return IsAdult && CanTriggerLACS;}}),
}, {
//Exits
Entrance(TOT_ENTRANCE, {[]{return true;}}),
Entrance(TOT_BEYOND_DOOR_OF_TIME, {[]{return OpenDoorOfTime.Is(OPENDOOROFTIME_OPEN) || (CanPlay(SongOfTime) && (OpenDoorOfTime.Is(OPENDOOROFTIME_SONGONLY) || (HasAllStones && OcarinaOfTime)));}}),
Entrance(RR_TOT_ENTRANCE, {[]{return true;}}),
Entrance(RR_TOT_BEYOND_DOOR_OF_TIME, {[]{return OpenDoorOfTime.Is(OPENDOOROFTIME_OPEN) || (CanPlay(SongOfTime) && (OpenDoorOfTime.Is(OPENDOOROFTIME_SONGONLY) || (HasAllStones && OcarinaOfTime)));}}),
});
areaTable[TOT_BEYOND_DOOR_OF_TIME] = Area("Beyond Door of Time", "Beyond Door of Time", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_TOT_BEYOND_DOOR_OF_TIME] = Area("Beyond Door of Time", "Beyond Door of Time", RHT_TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {
//Events
//EventAccess(&TimeTravel, {[]{return true;}}),
}, {
//Locations
LocationAccess(SHEIK_AT_TEMPLE, {[]{return ForestMedallion && IsAdult;}}),
LocationAccess(RC_SHEIK_AT_TEMPLE, {[]{return ForestMedallion && IsAdult;}}),
}, {
//Exits
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
Entrance(RR_TEMPLE_OF_TIME, {[]{return true;}}),
});
areaTable[CASTLE_GROUNDS] = Area("Castle Grounds", "Castle Grounds", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_CASTLE_GROUNDS] = Area("Castle Grounds", "Castle Grounds", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(THE_MARKET, {[]{return true;}}),
Entrance(HYRULE_CASTLE_GROUNDS, {[]{return IsChild;}}),
Entrance(GANONS_CASTLE_GROUNDS, {[]{return IsAdult;}}),
Entrance(RR_THE_MARKET, {[]{return true;}}),
Entrance(RR_HYRULE_CASTLE_GROUNDS, {[]{return IsChild;}}),
Entrance(RR_GANONS_CASTLE_GROUNDS, {[]{return IsAdult;}}),
});
areaTable[HYRULE_CASTLE_GROUNDS] = Area("Hyrule Castle Grounds", "Castle Grounds", HYRULE_CASTLE, DAY_NIGHT_CYCLE, {
areaTable[RR_HYRULE_CASTLE_GROUNDS] = Area("Hyrule Castle Grounds", "Castle Grounds", RHT_HYRULE_CASTLE, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(STICKS);}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(RG_STICKS);}}),
EventAccess(&BugRock, {[]{return true;}}),
}, {
//Locations
LocationAccess(HC_MALON_EGG, {[]{return true;}}),
LocationAccess(HC_GS_TREE, {[]{return CanChildAttack;}}),
LocationAccess(HC_MALON_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(HC_ROCK_WALL_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_HC_MALON_EGG, {[]{return true;}}),
LocationAccess(RC_HC_GS_TREE, {[]{return CanChildAttack;}}),
LocationAccess(RC_HC_MALON_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_HC_ROCK_WALL_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
Entrance(HC_GARDEN, {[]{return WeirdEgg || !ShuffleWeirdEgg;}}),
Entrance(HC_GREAT_FAIRY_FOUNTAIN, {[]{return CanBlastOrSmash;}}),
Entrance(HC_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}),
Entrance(RR_HC_GARDEN, {[]{return WeirdEgg || !ShuffleWeirdEgg;}}),
Entrance(RR_HC_GREAT_FAIRY_FOUNTAIN, {[]{return CanBlastOrSmash;}}),
Entrance(RR_HC_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
});
areaTable[HC_GARDEN] = Area("HC Garden", "Castle Grounds", HYRULE_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_HC_GARDEN] = Area("HC Garden", "Castle Grounds", RHT_HYRULE_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
}, {
//Locations
LocationAccess(HC_ZELDAS_LETTER, {[]{return true;}}),
LocationAccess(SONG_FROM_IMPA, {[]{return true;}}),
LocationAccess(RC_HC_ZELDAS_LETTER, {[]{return true;}}),
LocationAccess(RC_SONG_FROM_IMPA, {[]{return true;}}),
}, {
//Exits
Entrance(HYRULE_CASTLE_GROUNDS, {[]{return true;}}),
Entrance(RR_HYRULE_CASTLE_GROUNDS, {[]{return true;}}),
});
areaTable[HC_GREAT_FAIRY_FOUNTAIN] = Area("HC Great Fairy Fountain", "HC Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_HC_GREAT_FAIRY_FOUNTAIN] = Area("HC Great Fairy Fountain", "HC Great Fairy Fountain", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(HC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_HC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
}, {
//Exits
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}),
});
areaTable[HC_STORMS_GROTTO] = Area("HC Storms Grotto", "HC Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_HC_STORMS_GROTTO] = Area("HC Storms Grotto", "HC Storms Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&NutPot, {[]{return NutPot || CanBlastOrSmash;}}),
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || (CanBlastOrSmash && CanSummonGossipFairy);}}),
EventAccess(&WanderingBugs, {[]{return WanderingBugs || CanBlastOrSmash;}}),
}, {
//Locations
LocationAccess(HC_GS_STORMS_GROTTO, {[]{return (CanBlastOrSmash && HookshotOrBoomerang) || (Boomerang && LogicCastleStormsGS);}}),
LocationAccess(HC_STORMS_GROTTO_GOSSIP_STONE, {[]{return CanBlastOrSmash;}}),
LocationAccess(RC_HC_GS_STORMS_GROTTO, {[]{return (CanBlastOrSmash && HookshotOrBoomerang) || (Boomerang && LogicCastleStormsGS);}}),
LocationAccess(RC_HC_STORMS_GROTTO_GOSSIP_STONE, {[]{return CanBlastOrSmash;}}),
}, {
//Exits
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}),
});
areaTable[GANONS_CASTLE_GROUNDS] = Area("Ganon's Castle Grounds", "Castle Grounds", OUTSIDE_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_GROUNDS] = Area("Ganon's Castle Grounds", "Castle Grounds", RHT_OUTSIDE_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
EventAccess(&BuiltRainbowBridge, {[]{return CanBuildRainbowBridge;}}),
}, {
//Locations //the terrain was lowered such that you can't get this GS with a simple sword slash
LocationAccess(OGC_GS, {[]{return CanJumpslash || CanUseProjectile
|| (CanShield && CanUse(MEGATON_HAMMER)) || CanUse(DINS_FIRE);}}),
LocationAccess(RC_OGC_GS, {[]{return CanJumpslash || CanUseProjectile
|| (CanShield && CanUse(RG_MEGATON_HAMMER)) || CanUse(RG_DINS_FIRE);}}),
}, {
//Exits
Entrance(CASTLE_GROUNDS, {[]{return AtNight;}}),
Entrance(OGC_GREAT_FAIRY_FOUNTAIN, {[]{return CanUse(GOLDEN_GAUNTLETS) && AtNight;}}),
Entrance(GANONS_CASTLE_LEDGE, {[]{return BuiltRainbowBridge;}}),
Entrance(RR_CASTLE_GROUNDS, {[]{return AtNight;}}),
Entrance(RR_OGC_GREAT_FAIRY_FOUNTAIN, {[]{return CanUse(RG_GOLDEN_GAUNTLETS) && AtNight;}}),
Entrance(RR_GANONS_CASTLE_LEDGE, {[]{return BuiltRainbowBridge;}}),
});
areaTable[OGC_GREAT_FAIRY_FOUNTAIN] = Area("OGC Great Fairy Fountain", "OGC Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_OGC_GREAT_FAIRY_FOUNTAIN] = Area("OGC Great Fairy Fountain", "OGC Great Fairy Fountain", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(OGC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_OGC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
}, {
//Exits
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
Entrance(RR_CASTLE_GROUNDS, {[]{return true;}}),
});
areaTable[CASTLE_GROUNDS_FROM_GANONS_CASTLE] = Area("Castle Grounds From Ganon's Castle", "Castle Grounds From Ganon's Castle", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE] = Area("Castle Grounds From Ganon's Castle", "Castle Grounds From Ganon's Castle", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
// Exits
Entrance(HYRULE_CASTLE_GROUNDS, { [] { return IsChild; }}),
Entrance(GANONS_CASTLE_LEDGE, { [] { return IsAdult; }}),
Entrance(RR_HYRULE_CASTLE_GROUNDS, { [] { return IsChild; }}),
Entrance(RR_GANONS_CASTLE_LEDGE, { [] { return IsAdult; }}),
});
areaTable[GANONS_CASTLE_LEDGE] = Area("Ganon's Castle Ledge", "OGC Ganon's Castle Ledge", NONE, NO_DAY_NIGHT_CYCLE,
areaTable[RR_GANONS_CASTLE_LEDGE] = Area("Ganon's Castle Ledge", "OGC Ganon's Castle Ledge", RHT_NONE, NO_DAY_NIGHT_CYCLE,
{}, {}, {
// Exits
Entrance(GANONS_CASTLE_GROUNDS, {[]{return BuiltRainbowBridge;}}),
Entrance(GANONS_CASTLE_ENTRYWAY, {[]{return IsAdult;}}),
Entrance(RR_GANONS_CASTLE_GROUNDS, {[]{return BuiltRainbowBridge;}}),
Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return IsAdult;}}),
});
areaTable[MARKET_GUARD_HOUSE] = Area("Market Guard House", "Market Guard House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_MARKET_GUARD_HOUSE] = Area("Market Guard House", "Market Guard House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_10_BIG_POES, {[]{return IsAdult && BigPoeKill;}}),
LocationAccess(MARKET_GS_GUARD_HOUSE, {[]{return IsChild;}}),
LocationAccess(RC_MARKET_10_BIG_POES, {[]{return IsAdult && BigPoeKill;}}),
LocationAccess(RC_MARKET_GS_GUARD_HOUSE, {[]{return IsChild;}}),
}, {
//Exits
Entrance(MARKET_ENTRANCE, {[]{return true;}}),
Entrance(RR_MARKET_ENTRANCE, {[]{return true;}}),
});
areaTable[MARKET_BAZAAR] = Area("Market Bazaar", "Market Bazaar", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_MARKET_BAZAAR] = Area("Market Bazaar", "Market Bazaar", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_BAZAAR_ITEM_1, {[]{return true;}}),
LocationAccess(MARKET_BAZAAR_ITEM_2, {[]{return true;}}),
LocationAccess(MARKET_BAZAAR_ITEM_3, {[]{return true;}}),
LocationAccess(MARKET_BAZAAR_ITEM_4, {[]{return true;}}),
LocationAccess(MARKET_BAZAAR_ITEM_5, {[]{return true;}}),
LocationAccess(MARKET_BAZAAR_ITEM_6, {[]{return true;}}),
LocationAccess(MARKET_BAZAAR_ITEM_7, {[]{return true;}}),
LocationAccess(MARKET_BAZAAR_ITEM_8, {[]{return true;}}),
LocationAccess(RC_MARKET_BAZAAR_ITEM_1, {[]{return true;}}),
LocationAccess(RC_MARKET_BAZAAR_ITEM_2, {[]{return true;}}),
LocationAccess(RC_MARKET_BAZAAR_ITEM_3, {[]{return true;}}),
LocationAccess(RC_MARKET_BAZAAR_ITEM_4, {[]{return true;}}),
LocationAccess(RC_MARKET_BAZAAR_ITEM_5, {[]{return true;}}),
LocationAccess(RC_MARKET_BAZAAR_ITEM_6, {[]{return true;}}),
LocationAccess(RC_MARKET_BAZAAR_ITEM_7, {[]{return true;}}),
LocationAccess(RC_MARKET_BAZAAR_ITEM_8, {[]{return true;}}),
}, {
//Exits
Entrance(THE_MARKET, {[]{return true;}}),
Entrance(RR_THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_MASK_SHOP] = Area("Market Mask Shop", "Market Mask Shop", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_MARKET_MASK_SHOP] = Area("Market Mask Shop", "Market Mask Shop", RHT_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)));}}),
EventAccess(&SkullMask, {[]{return SkullMask || (ZeldasLetter && (CompleteMaskQuest || ChildCanAccess(RR_KAKARIKO_VILLAGE)));}}),
EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (CompleteMaskQuest || (ChildCanAccess(RR_THE_LOST_WOODS) && CanPlay(SariasSong) && AreaTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && HasAllStones)));}}),
}, {}, {
//Exits
Entrance(THE_MARKET, {[]{return true;}}),
Entrance(RR_THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_SHOOTING_GALLERY] = Area("Market Shooting Gallery", "Market Shooting Gallery", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_MARKET_SHOOTING_GALLERY] = Area("Market Shooting Gallery", "Market Shooting Gallery", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_SHOOTING_GALLERY_REWARD, {[]{return IsChild;}}),
LocationAccess(RC_MARKET_SHOOTING_GALLERY_REWARD, {[]{return IsChild;}}),
}, {
//Exits
Entrance(THE_MARKET, {[]{return true;}}),
Entrance(RR_THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_BOMBCHU_BOWLING] = Area("Market Bombchu Bowling", "Market Bombchu Bowling", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_MARKET_BOMBCHU_BOWLING] = Area("Market Bombchu Bowling", "Market Bombchu Bowling", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, {[]{return CanPlayBowling;}}),
LocationAccess(MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, {[]{return CanPlayBowling;}}),
LocationAccess(MARKET_BOMBCHU_BOWLING_BOMBCHUS, {[]{return CanPlayBowling;}}),
LocationAccess(RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, {[]{return CanPlayBowling;}}),
LocationAccess(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, {[]{return CanPlayBowling;}}),
LocationAccess(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, {[]{return CanPlayBowling;}}),
}, {
//Exits
Entrance(THE_MARKET, {[]{return true;}}),
Entrance(RR_THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_POTION_SHOP] = Area("Market Potion Shop", "Market Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_MARKET_POTION_SHOP] = Area("Market Potion Shop", "Market Potion Shop", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_POTION_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(MARKET_POTION_SHOP_ITEM_2, {[]{return true;}}),
LocationAccess(MARKET_POTION_SHOP_ITEM_3, {[]{return true;}}),
LocationAccess(MARKET_POTION_SHOP_ITEM_4, {[]{return true;}}),
LocationAccess(MARKET_POTION_SHOP_ITEM_5, {[]{return true;}}),
LocationAccess(MARKET_POTION_SHOP_ITEM_6, {[]{return true;}}),
LocationAccess(MARKET_POTION_SHOP_ITEM_7, {[]{return true;}}),
LocationAccess(MARKET_POTION_SHOP_ITEM_8, {[]{return true;}}),
LocationAccess(RC_MARKET_POTION_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(RC_MARKET_POTION_SHOP_ITEM_2, {[]{return true;}}),
LocationAccess(RC_MARKET_POTION_SHOP_ITEM_3, {[]{return true;}}),
LocationAccess(RC_MARKET_POTION_SHOP_ITEM_4, {[]{return true;}}),
LocationAccess(RC_MARKET_POTION_SHOP_ITEM_5, {[]{return true;}}),
LocationAccess(RC_MARKET_POTION_SHOP_ITEM_6, {[]{return true;}}),
LocationAccess(RC_MARKET_POTION_SHOP_ITEM_7, {[]{return true;}}),
LocationAccess(RC_MARKET_POTION_SHOP_ITEM_8, {[]{return true;}}),
}, {
//Exits
Entrance(THE_MARKET, {[]{return true;}}),
Entrance(RR_THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "Market Treasure Chest Game", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "Market Treasure Chest Game", RHT_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));}}),
LocationAccess(MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 1)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
LocationAccess(MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 2)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
LocationAccess(MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 3)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
LocationAccess(MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 4)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
LocationAccess(MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 5)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 6)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1));}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 2)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_3, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 3)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_4, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 4)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
LocationAccess(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, {[]{return (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (CanUse(RG_LENS_OF_TRUTH) && !ShuffleChestMinigame);}}),
}, {
//Exits
Entrance(THE_MARKET, {[]{return true;}}),
Entrance(RR_THE_MARKET, {[]{return true;}}),
});
areaTable[MARKET_BOMBCHU_SHOP] = Area("Market Bombchu Shop", "Market Bombchu Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_MARKET_BOMBCHU_SHOP] = Area("Market Bombchu Shop", "Market Bombchu Shop", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_2, {[]{return true;}}),
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_3, {[]{return true;}}),
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_4, {[]{return true;}}),
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_5, {[]{return true;}}),
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_6, {[]{return true;}}),
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_7, {[]{return true;}}),
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_8, {[]{return true;}}),
LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_2, {[]{return true;}}),
LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_3, {[]{return true;}}),
LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_4, {[]{return true;}}),
LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_5, {[]{return true;}}),
LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_6, {[]{return true;}}),
LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_7, {[]{return true;}}),
LocationAccess(RC_MARKET_BOMBCHU_SHOP_ITEM_8, {[]{return true;}}),
}, {
//Exits
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
Entrance(RR_MARKET_BACK_ALLEY, {[]{return true;}}),
});
areaTable[MARKET_DOG_LADY_HOUSE] = Area("Market Dog Lady House", "Market Dog Lady House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_MARKET_DOG_LADY_HOUSE] = Area("Market Dog Lady House", "Market Dog Lady House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(MARKET_LOST_DOG, {[]{return IsChild && AtNight;}}),
LocationAccess(RC_MARKET_LOST_DOG, {[]{return IsChild && AtNight;}}),
}, {
//Exits
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
Entrance(RR_MARKET_BACK_ALLEY, {[]{return true;}}),
});
areaTable[MARKET_MAN_IN_GREEN_HOUSE] = Area("Market Man in Green House", "Market Man in Green House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_MARKET_MAN_IN_GREEN_HOUSE] = Area("Market Man in Green House", "Market Man in Green House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
Entrance(RR_MARKET_BACK_ALLEY, {[]{return true;}}),
});
}

View File

@@ -6,255 +6,255 @@ using namespace Logic;
using namespace Settings;
void AreaTable_Init_DeathMountain() {
areaTable[DEATH_MOUNTAIN_TRAIL] = Area("Death Mountain", "Death Mountain", DEATH_MOUNTAIN_TRAIL, DAY_NIGHT_CYCLE, {
areaTable[RR_DEATH_MOUNTAIN_TRAIL] = Area("Death Mountain", "Death Mountain", RHT_DEATH_MOUNTAIN_TRAIL, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(DEATH_MOUNTAIN_TRAIL) && CanPlay(SongOfStorms) && (HasExplosives || GoronBracelet));}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && CanPlay(SongOfStorms) && (HasExplosives || GoronBracelet));}}),
}, {
//Locations
LocationAccess(DMT_CHEST, {[]{return CanBlastOrSmash || (LogicDMTBombable && IsChild && GoronBracelet);}}),
LocationAccess(DMT_FREESTANDING_POH, {[]{return CanTakeDamage || CanUse(HOVER_BOOTS) || (IsAdult && CanPlantBean(DEATH_MOUNTAIN_TRAIL) && (HasExplosives || GoronBracelet));}}),
LocationAccess(DMT_GS_BEAN_PATCH, {[]{return CanPlantBugs && (HasExplosives || GoronBracelet || (LogicDMTSoilGS && (CanTakeDamage || CanUse(HOVER_BOOTS)) && CanUse(BOOMERANG)));}}),
LocationAccess(DMT_GS_NEAR_KAK, {[]{return CanBlastOrSmash;}}),
LocationAccess(DMT_GS_ABOVE_DODONGOS_CAVERN, {[]{return IsAdult && AtNight && (CanUse(MEGATON_HAMMER) || (LogicDMTGSLowerHookshot && CanUse(HOOKSHOT)) || (LogicDMTGSLowerBean && CanPlantBean(DEATH_MOUNTAIN_TRAIL)) || (LogicDMTGSLowerHovers && CanUse(HOVER_BOOTS)) || LogicDMTGSLowerJS) && CanGetNightTimeGS;}}),
LocationAccess(RC_DMT_CHEST, {[]{return CanBlastOrSmash || (LogicDMTBombable && IsChild && GoronBracelet);}}),
LocationAccess(RC_DMT_FREESTANDING_POH, {[]{return CanTakeDamage || CanUse(RG_HOVER_BOOTS) || (IsAdult && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && (HasExplosives || GoronBracelet));}}),
LocationAccess(RC_DMT_GS_BEAN_PATCH, {[]{return CanPlantBugs && (HasExplosives || GoronBracelet || (LogicDMTSoilGS && (CanTakeDamage || CanUse(RG_HOVER_BOOTS)) && CanUse(RG_BOOMERANG)));}}),
LocationAccess(RC_DMT_GS_NEAR_KAK, {[]{return CanBlastOrSmash;}}),
LocationAccess(RC_DMT_GS_ABOVE_DODONGOS_CAVERN, {[]{return IsAdult && AtNight && (CanUse(RG_MEGATON_HAMMER) || (LogicDMTGSLowerHookshot && CanUse(RG_HOOKSHOT)) || (LogicDMTGSLowerBean && CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL)) || (LogicDMTGSLowerHovers && CanUse(RG_HOVER_BOOTS)) || LogicDMTGSLowerJS) && CanGetNightTimeGS;}}),
}, {
//Exits
Entrance(KAK_BEHIND_GATE, {[]{return true;}}),
Entrance(GORON_CITY, {[]{return true;}}),
Entrance(DEATH_MOUNTAIN_SUMMIT, {[]{return Here(DEATH_MOUNTAIN_TRAIL, []{return CanBlastOrSmash;}) || (IsAdult && ((CanPlantBean(DEATH_MOUNTAIN_TRAIL) && GoronBracelet) || (HoverBoots && LogicDMTClimbHovers)));}}),
Entrance(DODONGOS_CAVERN_ENTRYWAY, {[]{return HasExplosives || GoronBracelet || IsAdult;}}),
Entrance(DMT_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
Entrance(RR_KAK_BEHIND_GATE, {[]{return true;}}),
Entrance(RR_GORON_CITY, {[]{return true;}}),
Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return Here(RR_DEATH_MOUNTAIN_TRAIL, []{return CanBlastOrSmash;}) || (IsAdult && ((CanPlantBean(RR_DEATH_MOUNTAIN_TRAIL) && GoronBracelet) || (HoverBoots && LogicDMTClimbHovers)));}}),
Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, {[]{return HasExplosives || GoronBracelet || IsAdult;}}),
Entrance(RR_DMT_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
});
areaTable[DEATH_MOUNTAIN_SUMMIT] = Area("Death Mountain Summit", "Death Mountain", DEATH_MOUNTAIN_TRAIL, DAY_NIGHT_CYCLE, {
areaTable[RR_DEATH_MOUNTAIN_SUMMIT] = Area("Death Mountain Summit", "Death Mountain", RHT_DEATH_MOUNTAIN_TRAIL, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&PrescriptionAccess, {[]{return PrescriptionAccess || (IsAdult && (BrokenSwordAccess || BrokenSword));}}),
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
EventAccess(&BugRock, {[]{return BugRock || IsChild;}}),
}, {
//Locations
LocationAccess(DMT_TRADE_BROKEN_SWORD, {[]{return IsAdult && BrokenSword;}}),
LocationAccess(DMT_TRADE_EYEDROPS, {[]{return IsAdult && Eyedrops;}}),
LocationAccess(DMT_TRADE_CLAIM_CHECK, {[]{return IsAdult && ClaimCheck;}}),
LocationAccess(DMT_GS_FALLING_ROCKS_PATH, {[]{return IsAdult && AtNight && (CanUse(MEGATON_HAMMER) || LogicDMTGSUpper) && CanGetNightTimeGS;}}),
LocationAccess(DMT_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_DMT_TRADE_BROKEN_SWORD, {[]{return IsAdult && BrokenSword;}}),
LocationAccess(RC_DMT_TRADE_EYEDROPS, {[]{return IsAdult && Eyedrops;}}),
LocationAccess(RC_DMT_TRADE_CLAIM_CHECK, {[]{return IsAdult && ClaimCheck;}}),
LocationAccess(RC_DMT_GS_FALLING_ROCKS_PATH, {[]{return IsAdult && AtNight && (CanUse(RG_MEGATON_HAMMER) || LogicDMTGSUpper) && CanGetNightTimeGS;}}),
LocationAccess(RC_DMT_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
Entrance(DMC_UPPER_LOCAL, {[]{return true;}}),
Entrance(DMT_OWL_FLIGHT, {[]{return IsChild;}}),
Entrance(DMT_COW_GROTTO, {[]{return Here(DEATH_MOUNTAIN_SUMMIT, []{return CanBlastOrSmash;});}}),
Entrance(DMT_GREAT_FAIRY_FOUNTAIN, {[]{return Here(DEATH_MOUNTAIN_SUMMIT, []{return CanBlastOrSmash;});}}),
Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
Entrance(RR_DMC_UPPER_LOCAL, {[]{return true;}}),
Entrance(RR_DMT_OWL_FLIGHT, {[]{return IsChild;}}),
Entrance(RR_DMT_COW_GROTTO, {[]{return Here(RR_DEATH_MOUNTAIN_SUMMIT, []{return CanBlastOrSmash;});}}),
Entrance(RR_DMT_GREAT_FAIRY_FOUNTAIN, {[]{return Here(RR_DEATH_MOUNTAIN_SUMMIT, []{return CanBlastOrSmash;});}}),
});
areaTable[DMT_OWL_FLIGHT] = Area("DMT Owl Flight", "Death Mountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DMT_OWL_FLIGHT] = Area("DMT Owl Flight", "Death Mountain", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KAK_IMPAS_ROOFTOP, {[]{return true;}}),
Entrance(RR_KAK_IMPAS_ROOFTOP, {[]{return true;}}),
});
areaTable[DMT_COW_GROTTO] = Area("DMT Cow Grotto", "DMT Cow Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DMT_COW_GROTTO] = Area("DMT Cow Grotto", "DMT Cow Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DMT_COW_GROTTO_COW, {[]{return CanPlay(EponasSong);}}),
LocationAccess(RC_DMT_COW_GROTTO_COW, {[]{return CanPlay(EponasSong);}}),
}, {
//Exits
Entrance(DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}),
Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}),
});
areaTable[DMT_STORMS_GROTTO] = Area("DMT Storms Grotto", "DMT Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[RR_DMT_STORMS_GROTTO] = Area("DMT Storms Grotto", "DMT Storms Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(DMT_STORMS_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(DMT_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_DMT_STORMS_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(RC_DMT_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
});
areaTable[DMT_GREAT_FAIRY_FOUNTAIN] = Area("DMT Great Fairy Fountain", "DMT Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DMT_GREAT_FAIRY_FOUNTAIN] = Area("DMT Great Fairy Fountain", "DMT Great Fairy Fountain", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DMT_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_DMT_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
}, {
//Exits
Entrance(DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}),
Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}),
});
areaTable[GORON_CITY] = Area("Goron City", "Goron City", GORON_CITY, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GORON_CITY] = Area("Goron City", "Goron City", RHT_GORON_CITY, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
EventAccess(&StickPot, {[]{return StickPot || IsChild;}}),
EventAccess(&BugRock, {[]{return BugRock || (CanBlastOrSmash || CanUse(SILVER_GAUNTLETS));}}),
EventAccess(&GoronCityChildFire, {[]{return GoronCityChildFire || (IsChild && CanUse(DINS_FIRE));}}),
EventAccess(&GCWoodsWarpOpen, {[]{return GCWoodsWarpOpen || (CanBlastOrSmash || CanUse(DINS_FIRE) || CanUse(BOW) || GoronBracelet || GoronCityChildFire);}}),
EventAccess(&BugRock, {[]{return BugRock || (CanBlastOrSmash || CanUse(RG_SILVER_GAUNTLETS));}}),
EventAccess(&GoronCityChildFire, {[]{return GoronCityChildFire || (IsChild && CanUse(RG_DINS_FIRE));}}),
EventAccess(&GCWoodsWarpOpen, {[]{return GCWoodsWarpOpen || (CanBlastOrSmash || CanUse(RG_DINS_FIRE) || CanUse(RG_FAIRY_BOW) || GoronBracelet || GoronCityChildFire);}}),
EventAccess(&GCDaruniasDoorOpenChild, {[]{return GCDaruniasDoorOpenChild || (IsChild && CanPlay(ZeldasLullaby));}}),
EventAccess(&StopGCRollingGoronAsAdult, {[]{return StopGCRollingGoronAsAdult || (IsAdult && (GoronBracelet || HasExplosives || Bow || (LogicGoronCityLinkGoronDins && CanUse(DINS_FIRE))));}}),
EventAccess(&StopGCRollingGoronAsAdult, {[]{return StopGCRollingGoronAsAdult || (IsAdult && (GoronBracelet || HasExplosives || Bow || (LogicGoronCityLinkGoronDins && CanUse(RG_DINS_FIRE))));}}),
}, {
//Locations
LocationAccess(GC_MAZE_LEFT_CHEST, {[]{return CanUse(MEGATON_HAMMER) || CanUse(SILVER_GAUNTLETS) || (LogicGoronCityLeftMost && HasExplosives && CanUse(HOVER_BOOTS));}}),
LocationAccess(GC_MAZE_CENTER_CHEST, {[]{return CanBlastOrSmash || CanUse(SILVER_GAUNTLETS);}}),
LocationAccess(GC_MAZE_RIGHT_CHEST, {[]{return CanBlastOrSmash || CanUse(SILVER_GAUNTLETS);}}),
LocationAccess(GC_POT_FREESTANDING_POH, {[]{return IsChild && GoronCityChildFire && (Bombs || (GoronBracelet && LogicGoronCityPotWithStrength) || (HasBombchus && LogicGoronCityPot));}}),
LocationAccess(GC_ROLLING_GORON_AS_CHILD, {[]{return IsChild && (HasExplosives || (GoronBracelet && LogicChildRollingWithStrength));}}),
LocationAccess(GC_ROLLING_GORON_AS_ADULT, {[]{return StopGCRollingGoronAsAdult;}}),
LocationAccess(GC_GS_BOULDER_MAZE, {[]{return IsChild && CanBlastOrSmash;}}),
LocationAccess(GC_GS_CENTER_PLATFORM, {[]{return IsAdult;}}),
LocationAccess(GC_MEDIGORON, {[]{return IsAdult && AdultsWallet && (CanBlastOrSmash || GoronBracelet);}}),
LocationAccess(GC_MAZE_GOSSIP_STONE, {[]{return CanBlastOrSmash || CanUse(SILVER_GAUNTLETS);}}),
LocationAccess(GC_MEDIGORON_GOSSIP_STONE, {[]{return CanBlastOrSmash || GoronBracelet;}}),
LocationAccess(RC_GC_MAZE_LEFT_CHEST, {[]{return CanUse(RG_MEGATON_HAMMER) || CanUse(RG_SILVER_GAUNTLETS) || (LogicGoronCityLeftMost && HasExplosives && CanUse(RG_HOVER_BOOTS));}}),
LocationAccess(RC_GC_MAZE_CENTER_CHEST, {[]{return CanBlastOrSmash || CanUse(RG_SILVER_GAUNTLETS);}}),
LocationAccess(RC_GC_MAZE_RIGHT_CHEST, {[]{return CanBlastOrSmash || CanUse(RG_SILVER_GAUNTLETS);}}),
LocationAccess(RC_GC_POT_FREESTANDING_POH, {[]{return IsChild && GoronCityChildFire && (Bombs || (GoronBracelet && LogicGoronCityPotWithStrength) || (HasBombchus && LogicGoronCityPot));}}),
LocationAccess(RC_GC_ROLLING_GORON_AS_CHILD, {[]{return IsChild && (HasExplosives || (GoronBracelet && LogicChildRollingWithStrength));}}),
LocationAccess(RC_GC_ROLLING_GORON_AS_ADULT, {[]{return StopGCRollingGoronAsAdult;}}),
LocationAccess(RC_GC_GS_BOULDER_MAZE, {[]{return IsChild && CanBlastOrSmash;}}),
LocationAccess(RC_GC_GS_CENTER_PLATFORM, {[]{return IsAdult;}}),
LocationAccess(RC_GC_MEDIGORON, {[]{return IsAdult && AdultsWallet && (CanBlastOrSmash || GoronBracelet);}}),
LocationAccess(RC_GC_MAZE_GOSSIP_STONE, {[]{return CanBlastOrSmash || CanUse(RG_SILVER_GAUNTLETS);}}),
LocationAccess(RC_GC_MEDIGORON_GOSSIP_STONE, {[]{return CanBlastOrSmash || GoronBracelet;}}),
}, {
//Exits
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
Entrance(GC_WOODS_WARP, {[]{return GCWoodsWarpOpen;}}),
Entrance(GC_SHOP, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || (IsChild && (CanBlastOrSmash || GoronBracelet || GoronCityChildFire || CanUse(BOW)));}}),
Entrance(GC_DARUNIAS_CHAMBER, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || GCDaruniasDoorOpenChild;}}),
Entrance(GC_GROTTO_PLATFORM, {[]{return IsAdult && ((CanPlay(SongOfTime) && ((EffectiveHealth > 2) || CanUse(GORON_TUNIC) || CanUse(LONGSHOT) || CanUse(NAYRUS_LOVE))) || (EffectiveHealth > 1 && CanUse(GORON_TUNIC) && CanUse(HOOKSHOT)) || (CanUse(NAYRUS_LOVE) && CanUse(HOOKSHOT)) || (EffectiveHealth > 2 && CanUse(HOOKSHOT) && LogicGoronCityGrotto));}}),
Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
Entrance(RR_GC_WOODS_WARP, {[]{return GCWoodsWarpOpen;}}),
Entrance(RR_GC_SHOP, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || (IsChild && (CanBlastOrSmash || GoronBracelet || GoronCityChildFire || CanUse(RG_FAIRY_BOW)));}}),
Entrance(RR_GC_DARUNIAS_CHAMBER, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || GCDaruniasDoorOpenChild;}}),
Entrance(RR_GC_GROTTO_PLATFORM, {[]{return IsAdult && ((CanPlay(SongOfTime) && ((EffectiveHealth > 2) || CanUse(RG_GORON_TUNIC) || CanUse(RG_LONGSHOT) || CanUse(RG_NAYRUS_LOVE))) || (EffectiveHealth > 1 && CanUse(RG_GORON_TUNIC) && CanUse(RG_HOOKSHOT)) || (CanUse(RG_NAYRUS_LOVE) && CanUse(RG_HOOKSHOT)) || (EffectiveHealth > 2 && CanUse(RG_HOOKSHOT) && LogicGoronCityGrotto));}}),
});
areaTable[GC_WOODS_WARP] = Area("GC Woods Warp", "Goron City", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GC_WOODS_WARP] = Area("GC Woods Warp", "Goron City", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GCWoodsWarpOpen, {[]{return GCWoodsWarpOpen || (CanBlastOrSmash || CanUse(DINS_FIRE));}}),
EventAccess(&GCWoodsWarpOpen, {[]{return GCWoodsWarpOpen || (CanBlastOrSmash || CanUse(RG_DINS_FIRE));}}),
}, {}, {
//Exits
Entrance(GORON_CITY, {[]{return CanLeaveForest && GCWoodsWarpOpen;}}),
Entrance(THE_LOST_WOODS, {[]{return true;}}),
Entrance(RR_GORON_CITY, {[]{return CanLeaveForest && GCWoodsWarpOpen;}}),
Entrance(RR_THE_LOST_WOODS, {[]{return true;}}),
});
areaTable[GC_DARUNIAS_CHAMBER] = Area("GC Darunias Chamber", "Goron City", GORON_CITY, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GC_DARUNIAS_CHAMBER] = Area("GC Darunias Chamber", "Goron City", RHT_GORON_CITY, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GoronCityChildFire, {[]{return GoronCityChildFire || (IsChild && CanUse(STICKS));}}),
EventAccess(&GoronCityChildFire, {[]{return GoronCityChildFire || (IsChild && CanUse(RG_STICKS));}}),
}, {
//Locations
LocationAccess(GC_DARUNIAS_JOY, {[]{return IsChild && CanPlay(SariasSong);}}),
LocationAccess(RC_GC_DARUNIAS_JOY, {[]{return IsChild && CanPlay(SariasSong);}}),
}, {
//Exits
Entrance(GORON_CITY, {[]{return true;}}),
Entrance(DMC_LOWER_LOCAL, {[]{return IsAdult;}}),
Entrance(RR_GORON_CITY, {[]{return true;}}),
Entrance(RR_DMC_LOWER_LOCAL, {[]{return IsAdult;}}),
});
areaTable[GC_GROTTO_PLATFORM] = Area("GC Grotto Platform", "Goron City", GORON_CITY, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_GC_GROTTO_PLATFORM] = Area("GC Grotto Platform", "Goron City", RHT_GORON_CITY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GC_GROTTO, {[]{return true;}}),
Entrance(GORON_CITY, {[]{return EffectiveHealth > 2 || CanUse(GORON_TUNIC) || CanUse(NAYRUS_LOVE) || ((IsChild || CanPlay(SongOfTime)) && CanUse(LONGSHOT));}}),
Entrance(RR_GC_GROTTO, {[]{return true;}}),
Entrance(RR_GORON_CITY, {[]{return EffectiveHealth > 2 || CanUse(RG_GORON_TUNIC) || CanUse(RG_NAYRUS_LOVE) || ((IsChild || CanPlay(SongOfTime)) && CanUse(RG_LONGSHOT));}}),
});
areaTable[GC_SHOP] = Area("GC Shop", "GC Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GC_SHOP] = Area("GC Shop", "GC Shop", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GC_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(GC_SHOP_ITEM_2, {[]{return true;}}),
LocationAccess(GC_SHOP_ITEM_3, {[]{return true;}}),
LocationAccess(GC_SHOP_ITEM_4, {[]{return true;}}),
LocationAccess(GC_SHOP_ITEM_5, {[]{return true;}}),
LocationAccess(GC_SHOP_ITEM_6, {[]{return true;}}),
LocationAccess(GC_SHOP_ITEM_7, {[]{return true;}}),
LocationAccess(GC_SHOP_ITEM_8, {[]{return true;}}),
LocationAccess(RC_GC_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(RC_GC_SHOP_ITEM_2, {[]{return true;}}),
LocationAccess(RC_GC_SHOP_ITEM_3, {[]{return true;}}),
LocationAccess(RC_GC_SHOP_ITEM_4, {[]{return true;}}),
LocationAccess(RC_GC_SHOP_ITEM_5, {[]{return true;}}),
LocationAccess(RC_GC_SHOP_ITEM_6, {[]{return true;}}),
LocationAccess(RC_GC_SHOP_ITEM_7, {[]{return true;}}),
LocationAccess(RC_GC_SHOP_ITEM_8, {[]{return true;}}),
}, {
//Exits
Entrance(GORON_CITY, {[]{return true;}}),
Entrance(RR_GORON_CITY, {[]{return true;}}),
});
areaTable[GC_GROTTO] = Area("GC Grotto", "GC Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GC_GROTTO] = Area("GC Grotto", "GC Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(GC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(GC_DEKU_SCRUB_GROTTO_CENTER, {[]{return CanStunDeku;}}),
LocationAccess(RC_GC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GC_DEKU_SCRUB_GROTTO_CENTER, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(GC_GROTTO_PLATFORM, {[]{return true;}}),
Entrance(RR_GC_GROTTO_PLATFORM, {[]{return true;}}),
});
areaTable[DMC_UPPER_NEARBY] = Area("DMC Upper Nearby", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DMC_UPPER_NEARBY] = Area("DMC Upper Nearby", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DMC_UPPER_LOCAL, {[]{return FireTimer >= 48;}}),
Entrance(DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}),
Entrance(DMC_UPPER_GROTTO, {[]{return Here(DMC_UPPER_NEARBY, []{return CanBlastOrSmash && (FireTimer >= 8 || Hearts >= 3);});}})
Entrance(RR_DMC_UPPER_LOCAL, {[]{return FireTimer >= 48;}}),
Entrance(RR_DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}),
Entrance(RR_DMC_UPPER_GROTTO, {[]{return Here(RR_DMC_UPPER_NEARBY, []{return CanBlastOrSmash && (FireTimer >= 8 || Hearts >= 3);});}})
});
areaTable[DMC_UPPER_LOCAL] = Area("DMC Upper Local", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DMC_UPPER_LOCAL] = Area("DMC Upper Local", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || (HasExplosives && CanSummonGossipFairyWithoutSuns && (FireTimer >= 16 || Hearts >= 3));}}),
}, {
//Locations
LocationAccess(DMC_WALL_FREESTANDING_POH, {[]{return FireTimer >= 16 || Hearts >= 3;}}),
LocationAccess(DMC_GS_CRATE, {[]{return (FireTimer >= 8 || Hearts >= 3) && IsChild && CanChildAttack;}}),
LocationAccess(DMC_GOSSIP_STONE, {[]{return HasExplosives && (FireTimer >= 16 || Hearts >= 3);}}),
LocationAccess(RC_DMC_WALL_FREESTANDING_POH, {[]{return FireTimer >= 16 || Hearts >= 3;}}),
LocationAccess(RC_DMC_GS_CRATE, {[]{return (FireTimer >= 8 || Hearts >= 3) && IsChild && CanChildAttack;}}),
LocationAccess(RC_DMC_GOSSIP_STONE, {[]{return HasExplosives && (FireTimer >= 16 || Hearts >= 3);}}),
}, {
//Exits
Entrance(DMC_UPPER_NEARBY, {[]{return true;}}),
Entrance(DMC_LADDER_AREA_NEARBY, {[]{return FireTimer >= 16 || Hearts >= 3;}}),
Entrance(DMC_CENTRAL_NEARBY, {[]{return IsAdult && CanUse(GORON_TUNIC) && CanUse(DISTANT_SCARECROW) && ((EffectiveHealth > 2) || (Fairy && ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) || CanUse(NAYRUS_LOVE));}}),
Entrance(DMC_LOWER_NEARBY, {[]{return false;}}),
Entrance(RR_DMC_UPPER_NEARBY, {[]{return true;}}),
Entrance(RR_DMC_LADDER_AREA_NEARBY, {[]{return FireTimer >= 16 || Hearts >= 3;}}),
Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && CanUse(RG_DISTANT_SCARECROW) && ((EffectiveHealth > 2) || (Fairy && ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) || CanUse(RG_NAYRUS_LOVE));}}),
Entrance(RR_DMC_LOWER_NEARBY, {[]{return false;}}),
});
areaTable[DMC_LADDER_AREA_NEARBY] = Area("DMC Ladder Area Nearby", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DMC_LADDER_AREA_NEARBY] = Area("DMC Ladder Area Nearby", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DMC_DEKU_SCRUB, {[]{return IsChild && CanStunDeku;}}),
LocationAccess(RC_DMC_DEKU_SCRUB, {[]{return IsChild && CanStunDeku;}}),
}, {
//Exits
Entrance(DMC_UPPER_NEARBY, {[]{return Hearts >= 3;}}),
Entrance(DMC_LOWER_NEARBY, {[]{return Hearts >= 3 && (CanUse(HOVER_BOOTS) || (LogicCraterBoulderJS && IsAdult && CanUse(MEGATON_HAMMER)) || (LogicCraterBoulderSkip && IsAdult));}}),
Entrance(RR_DMC_UPPER_NEARBY, {[]{return Hearts >= 3;}}),
Entrance(RR_DMC_LOWER_NEARBY, {[]{return Hearts >= 3 && (CanUse(RG_HOVER_BOOTS) || (LogicCraterBoulderJS && IsAdult && CanUse(RG_MEGATON_HAMMER)) || (LogicCraterBoulderSkip && IsAdult));}}),
});
areaTable[DMC_LOWER_NEARBY] = Area("DMC Lower Nearby", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DMC_LOWER_NEARBY] = Area("DMC Lower Nearby", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DMC_LOWER_LOCAL, {[]{return FireTimer >= 48;}}),
Entrance(GC_DARUNIAS_CHAMBER, {[]{return true;}}),
Entrance(DMC_GREAT_FAIRY_FOUNTAIN, {[]{return CanUse(MEGATON_HAMMER);}}),
Entrance(DMC_HAMMER_GROTTO, {[]{return IsAdult && CanUse(MEGATON_HAMMER);}}),
Entrance(RR_DMC_LOWER_LOCAL, {[]{return FireTimer >= 48;}}),
Entrance(RR_GC_DARUNIAS_CHAMBER, {[]{return true;}}),
Entrance(RR_DMC_GREAT_FAIRY_FOUNTAIN, {[]{return CanUse(RG_MEGATON_HAMMER);}}),
Entrance(RR_DMC_HAMMER_GROTTO, {[]{return IsAdult && CanUse(RG_MEGATON_HAMMER);}}),
});
areaTable[DMC_LOWER_LOCAL] = Area("DMC Lower Local", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DMC_LOWER_LOCAL] = Area("DMC Lower Local", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DMC_LOWER_NEARBY, {[]{return true;}}),
Entrance(DMC_LADDER_AREA_NEARBY, {[]{return FireTimer >= 8 || Hearts >= 3;}}),
Entrance(DMC_CENTRAL_NEARBY, {[]{return (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT)) && (FireTimer >= 8 || Hearts >= 3);}}),
Entrance(DMC_CENTRAL_LOCAL, {[]{return (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT) || (IsAdult && CanShield && LogicCraterBoleroJump)) && FireTimer >= 24;}}),
Entrance(RR_DMC_LOWER_NEARBY, {[]{return true;}}),
Entrance(RR_DMC_LADDER_AREA_NEARBY, {[]{return FireTimer >= 8 || Hearts >= 3;}}),
Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT)) && (FireTimer >= 8 || Hearts >= 3);}}),
Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT) || (IsAdult && CanShield && LogicCraterBoleroJump)) && FireTimer >= 24;}}),
});
areaTable[DMC_CENTRAL_NEARBY] = Area("DMC Central Nearby", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DMC_CENTRAL_NEARBY] = Area("DMC Central Nearby", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DMC_VOLCANO_FREESTANDING_POH, {[]{return IsAdult && Hearts >= 3 && (CanPlantBean(DMC_CENTRAL_LOCAL) || (LogicCraterBeanPoHWithHovers && HoverBoots));}}),
LocationAccess(SHEIK_IN_CRATER, {[]{return IsAdult && (FireTimer >= 8 || Hearts >= 3);}}),
LocationAccess(RC_DMC_VOLCANO_FREESTANDING_POH, {[]{return IsAdult && Hearts >= 3 && (CanPlantBean(RR_DMC_CENTRAL_LOCAL) || (LogicCraterBeanPoHWithHovers && HoverBoots));}}),
LocationAccess(RC_SHEIK_IN_CRATER, {[]{return IsAdult && (FireTimer >= 8 || Hearts >= 3);}}),
}, {
//Exits
Entrance(DMC_CENTRAL_LOCAL, {[]{return FireTimer >= 48;}}),
Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return FireTimer >= 48;}}),
});
areaTable[DMC_CENTRAL_LOCAL] = Area("DMC Central Local", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DMC_CENTRAL_LOCAL] = Area("DMC Central Local", "Death Mountain Crater", RHT_DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(DMC_CENTRAL_LOCAL) && CanPlay(SongOfStorms));}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_DMC_CENTRAL_LOCAL) && CanPlay(SongOfStorms));}}),
}, {
//Locations
LocationAccess(DMC_GS_BEAN_PATCH, {[]{return (FireTimer >= 8 || Hearts >= 3) && CanPlantBugs && CanChildAttack;}}),
LocationAccess(RC_DMC_GS_BEAN_PATCH, {[]{return (FireTimer >= 8 || Hearts >= 3) && CanPlantBugs && CanChildAttack;}}),
}, {
//Exits
Entrance(DMC_CENTRAL_NEARBY, {[]{return true;}}),
Entrance(DMC_LOWER_NEARBY, {[]{return (IsAdult && CanPlantBean(DMC_CENTRAL_LOCAL)) || CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT);}}),
Entrance(DMC_UPPER_NEARBY, {[]{return IsAdult && CanPlantBean(DMC_CENTRAL_LOCAL);}}),
Entrance(FIRE_TEMPLE_ENTRYWAY, {[]{return (IsChild && Hearts >= 3 && ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) || (IsAdult && FireTimer >= 24);}}),
Entrance(RR_DMC_CENTRAL_NEARBY, {[]{return true;}}),
Entrance(RR_DMC_LOWER_NEARBY, {[]{return (IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL)) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT);}}),
Entrance(RR_DMC_UPPER_NEARBY, {[]{return IsAdult && CanPlantBean(RR_DMC_CENTRAL_LOCAL);}}),
Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return (IsChild && Hearts >= 3 && ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) || (IsAdult && FireTimer >= 24);}}),
});
areaTable[DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "DMC Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "DMC Great Fairy Fountain", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DMC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_DMC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
}, {
//Exits
Entrance(DMC_LOWER_LOCAL, {[]{return true;}}),
Entrance(RR_DMC_LOWER_LOCAL, {[]{return true;}}),
});
areaTable[DMC_UPPER_GROTTO] = Area("DMC Upper Grotto", "DMC Upper Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[RR_DMC_UPPER_GROTTO] = Area("DMC Upper Grotto", "DMC Upper Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(DMC_UPPER_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(DMC_UPPER_GROTTO_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_DMC_UPPER_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(RC_DMC_UPPER_GROTTO_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(DMC_UPPER_LOCAL, {[]{return true;}}),
Entrance(RR_DMC_UPPER_LOCAL, {[]{return true;}}),
});
areaTable[DMC_HAMMER_GROTTO] = Area("DMC Hammer Grotto", "DMC Hammer Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DMC_HAMMER_GROTTO] = Area("DMC Hammer Grotto", "DMC Hammer Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DMC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(DMC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(DMC_DEKU_SCRUB_GROTTO_CENTER, {[]{return CanStunDeku;}}),
LocationAccess(RC_DMC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(RC_DMC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(RC_DMC_DEKU_SCRUB_GROTTO_CENTER, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(DMC_LOWER_LOCAL, {[]{return true;}}),
Entrance(RR_DMC_LOWER_LOCAL, {[]{return true;}}),
});
}

View File

@@ -10,140 +10,140 @@ void AreaTable_Init_DekuTree() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[DEKU_TREE_ENTRYWAY] = Area("Deku Tree Entryway", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DEKU_TREE_ENTRYWAY] = Area("Deku Tree Entryway", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DEKU_TREE_LOBBY, {[]{return Dungeon::DekuTree.IsVanilla();}}),
Entrance(DEKU_TREE_MQ_LOBBY, {[]{return Dungeon::DekuTree.IsMQ();}}),
Entrance(KF_OUTSIDE_DEKU_TREE, {[]{return true;}}),
Entrance(RR_DEKU_TREE_LOBBY, {[]{return Dungeon::DekuTree.IsVanilla();}}),
Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return Dungeon::DekuTree.IsMQ();}}),
Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::DekuTree.IsVanilla()) {
areaTable[DEKU_TREE_LOBBY] = Area("Deku Tree Lobby", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DEKU_TREE_LOBBY] = Area("Deku Tree Lobby", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
}, {
//Locations
LocationAccess(DEKU_TREE_MAP_CHEST, {[]{return true;}}),
LocationAccess(RC_DEKU_TREE_MAP_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(DEKU_TREE_ENTRYWAY, {[]{return true;}}),
Entrance(DEKU_TREE_2F_MIDDLE_ROOM, {[]{return true;}}),
Entrance(DEKU_TREE_COMPASS_ROOM, {[]{return true;}}),
Entrance(DEKU_TREE_BASEMENT_LOWER, {[]{return Here(DEKU_TREE_LOBBY, []{return IsAdult || CanChildAttack || Nuts;});}}),
Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return false;}}),
Entrance(DEKU_TREE_BOSS_ENTRYWAY, {[]{return false;}}),
Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, {[]{return true;}}),
Entrance(RR_DEKU_TREE_COMPASS_ROOM, {[]{return true;}}),
Entrance(RR_DEKU_TREE_BASEMENT_LOWER, {[]{return Here(RR_DEKU_TREE_LOBBY, []{return IsAdult || CanChildAttack || Nuts;});}}),
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return false;}}),
Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, {[]{return false;}}),
});
areaTable[DEKU_TREE_2F_MIDDLE_ROOM] = Area("Deku Tree 2F Middle Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DEKU_TREE_2F_MIDDLE_ROOM] = Area("Deku Tree 2F Middle Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DEKU_TREE_LOBBY, {[]{return Here(DEKU_TREE_2F_MIDDLE_ROOM, []{return HasShield || CanUse(MEGATON_HAMMER);});}}),
Entrance(DEKU_TREE_SLINGSHOT_ROOM,{[]{return Here(DEKU_TREE_2F_MIDDLE_ROOM, []{return HasShield || CanUse(MEGATON_HAMMER);});}}),
Entrance(RR_DEKU_TREE_LOBBY, {[]{return Here(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return HasShield || CanUse(RG_MEGATON_HAMMER);});}}),
Entrance(RR_DEKU_TREE_SLINGSHOT_ROOM,{[]{return Here(RR_DEKU_TREE_2F_MIDDLE_ROOM, []{return HasShield || CanUse(RG_MEGATON_HAMMER);});}}),
});
areaTable[DEKU_TREE_SLINGSHOT_ROOM] = Area("Deku Tree Slingshot Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DEKU_TREE_SLINGSHOT_ROOM] = Area("Deku Tree Slingshot Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DEKU_TREE_SLINGSHOT_CHEST, {[]{return true;}}),
LocationAccess(DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, {[]{return true;}}),
LocationAccess(RC_DEKU_TREE_SLINGSHOT_CHEST, {[]{return true;}}),
LocationAccess(RC_DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(DEKU_TREE_2F_MIDDLE_ROOM, {[]{return CanUse(SLINGSHOT) || CanUse(HOVER_BOOTS);}}),
Entrance(RR_DEKU_TREE_2F_MIDDLE_ROOM, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_HOVER_BOOTS);}}),
});
areaTable[DEKU_TREE_COMPASS_ROOM] = Area("Deku Tree Compass Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DEKU_TREE_COMPASS_ROOM] = Area("Deku Tree Compass Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
}, {
//Locations
LocationAccess(DEKU_TREE_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, {[]{return true;}}),
LocationAccess(DEKU_TREE_GS_COMPASS_ROOM, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(RC_DEKU_TREE_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST, {[]{return true;}}),
LocationAccess(RC_DEKU_TREE_GS_COMPASS_ROOM, {[]{return IsAdult || CanChildAttack;}}),
}, {
//Exits
Entrance(DEKU_TREE_LOBBY, {[]{return HasFireSourceWithTorch || CanUse(BOW);}}),
Entrance(DEKU_TREE_BOSS_ENTRYWAY, {[]{return false;}}),
Entrance(RR_DEKU_TREE_LOBBY, {[]{return HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW);}}),
Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, {[]{return false;}}),
});
areaTable[DEKU_TREE_BASEMENT_LOWER] = Area("Deku Tree Basement Lower", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DEKU_TREE_BASEMENT_LOWER] = Area("Deku Tree Basement Lower", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));},
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));},
/*Glitched*/[]{return CanUse(RG_MEGATON_HAMMER);}}),
}, {
//Locations
LocationAccess(DEKU_TREE_BASEMENT_CHEST, {[]{return true;}}),
LocationAccess(DEKU_TREE_GS_BASEMENT_GATE, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(DEKU_TREE_GS_BASEMENT_VINES, {[]{return CanUseProjectile || CanUse(DINS_FIRE) || (LogicDekuBasementGS && (IsAdult || Sticks || KokiriSword));}}),
LocationAccess(RC_DEKU_TREE_BASEMENT_CHEST, {[]{return true;}}),
LocationAccess(RC_DEKU_TREE_GS_BASEMENT_GATE, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(RC_DEKU_TREE_GS_BASEMENT_VINES, {[]{return CanUseProjectile || CanUse(RG_DINS_FIRE) || (LogicDekuBasementGS && (IsAdult || Sticks || KokiriSword));}}),
}, {
//Exits
Entrance(DEKU_TREE_LOBBY, {[]{return true;}}),
Entrance(DEKU_TREE_BASEMENT_SCRUB_ROOM, {[]{return Here(DEKU_TREE_BASEMENT_LOWER, []{return HasFireSourceWithTorch || CanUse(BOW);});}}),
Entrance(DEKU_TREE_BASEMENT_UPPER, {[]{return IsAdult || LogicDekuB1Skip || HasAccessTo(DEKU_TREE_BASEMENT_UPPER);}}),
Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return false;}}),
Entrance(RR_DEKU_TREE_LOBBY, {[]{return true;}}),
Entrance(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, {[]{return Here(RR_DEKU_TREE_BASEMENT_LOWER, []{return HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW);});}}),
Entrance(RR_DEKU_TREE_BASEMENT_UPPER, {[]{return IsAdult || LogicDekuB1Skip || HasAccessTo(RR_DEKU_TREE_BASEMENT_UPPER);}}),
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return false;}}),
});
areaTable[DEKU_TREE_BASEMENT_SCRUB_ROOM] = Area("Deku Tree Basement Scrub Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DEKU_TREE_BASEMENT_SCRUB_ROOM] = Area("Deku Tree Basement Scrub Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DEKU_TREE_BASEMENT_LOWER, {[]{return true;}}),
Entrance(DEKU_TREE_BASEMENT_WATER_ROOM, {[]{return Here(DEKU_TREE_BASEMENT_SCRUB_ROOM, []{return CanUse(SLINGSHOT) || CanUse(BOW);});}}),
Entrance(RR_DEKU_TREE_BASEMENT_LOWER, {[]{return true;}}),
Entrance(RR_DEKU_TREE_BASEMENT_WATER_ROOM, {[]{return Here(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, []{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);});}}),
});
areaTable[DEKU_TREE_BASEMENT_WATER_ROOM] = Area("Deku Tree Basement Water Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DEKU_TREE_BASEMENT_WATER_ROOM] = Area("Deku Tree Basement Water Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DEKU_TREE_BASEMENT_SCRUB_ROOM, {[]{return true;}}),
Entrance(DEKU_TREE_BASEMENT_TORCH_ROOM, {[]{return true;}}),
Entrance(RR_DEKU_TREE_BASEMENT_SCRUB_ROOM, {[]{return true;}}),
Entrance(RR_DEKU_TREE_BASEMENT_TORCH_ROOM, {[]{return true;}}),
});
areaTable[DEKU_TREE_BASEMENT_TORCH_ROOM] = Area("Deku Tree Basement Torch Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DEKU_TREE_BASEMENT_TORCH_ROOM] = Area("Deku Tree Basement Torch Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
}, {}, {
//Exits
Entrance(DEKU_TREE_BASEMENT_WATER_ROOM, {[]{return true;}}),
Entrance(DEKU_TREE_BASEMENT_BACK_LOBBY, {[]{return Here(DEKU_TREE_BASEMENT_TORCH_ROOM, []{return HasFireSourceWithTorch || CanUse(BOW);});}}),
Entrance(RR_DEKU_TREE_BASEMENT_WATER_ROOM, {[]{return true;}}),
Entrance(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, {[]{return Here(RR_DEKU_TREE_BASEMENT_TORCH_ROOM, []{return HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW);});}}),
});
areaTable[DEKU_TREE_BASEMENT_BACK_LOBBY] = Area("Deku Tree Basement Back Lobby", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DEKU_TREE_BASEMENT_BACK_LOBBY] = Area("Deku Tree Basement Back Lobby", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (Here(DEKU_TREE_BASEMENT_BACK_LOBBY, []{return HasFireSourceWithTorch || CanUse(BOW);}) &&
(IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE)));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (Here(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, []{return HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW);}) &&
(IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE)));}}),
}, {}, {
//Exits
Entrance(DEKU_TREE_BASEMENT_TORCH_ROOM, {[]{return true;}}),
Entrance(DEKU_TREE_BASEMENT_BACK_ROOM, {[]{return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, []{return HasFireSourceWithTorch || CanUse(Bow);}) &&
Here(DEKU_TREE_BASEMENT_BACK_LOBBY, []{return CanBlastOrSmash;});}}),
Entrance(DEKU_TREE_BASEMENT_UPPER, {[]{return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, []{return HasFireSourceWithTorch || CanUse(Bow);}) && IsChild;}}),
Entrance(RR_DEKU_TREE_BASEMENT_TORCH_ROOM, {[]{return true;}}),
Entrance(RR_DEKU_TREE_BASEMENT_BACK_ROOM, {[]{return Here(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, []{return HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW);}) &&
Here(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, []{return CanBlastOrSmash;});}}),
Entrance(RR_DEKU_TREE_BASEMENT_UPPER, {[]{return Here(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, []{return HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW);}) && IsChild;}}),
});
areaTable[DEKU_TREE_BASEMENT_BACK_ROOM] = Area("Deku Tree Basement Back Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DEKU_TREE_BASEMENT_BACK_ROOM] = Area("Deku Tree Basement Back Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DEKU_TREE_GS_BASEMENT_BACK_ROOM, {[]{return HookshotOrBoomerang;}}),
LocationAccess(RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM, {[]{return HookshotOrBoomerang;}}),
}, {
//Exits
Entrance(DEKU_TREE_BASEMENT_BACK_LOBBY, {[]{return true;}}),
Entrance(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, {[]{return true;}}),
});
areaTable[DEKU_TREE_BASEMENT_UPPER] = Area("Deku Tree Basement Upper", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DEKU_TREE_BASEMENT_UPPER] = Area("Deku Tree Basement Upper", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
}, {}, {
//Exits
Entrance(DEKU_TREE_BASEMENT_LOWER, {[]{return true;}}),
Entrance(DEKU_TREE_BASEMENT_BACK_LOBBY, {[]{return IsChild;}}),
Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return Here(DEKU_TREE_BASEMENT_UPPER, []{return HasFireSourceWithTorch || (LogicDekuB1WebsWithBow && IsAdult && CanUse(BOW));});}}),
Entrance(RR_DEKU_TREE_BASEMENT_LOWER, {[]{return true;}}),
Entrance(RR_DEKU_TREE_BASEMENT_BACK_LOBBY, {[]{return IsChild;}}),
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return Here(RR_DEKU_TREE_BASEMENT_UPPER, []{return HasFireSourceWithTorch || (LogicDekuB1WebsWithBow && IsAdult && CanUse(RG_FAIRY_BOW));});}}),
});
areaTable[DEKU_TREE_OUTSIDE_BOSS_ROOM] = Area("Deku Tree Outside Boss Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DEKU_TREE_OUTSIDE_BOSS_ROOM] = Area("Deku Tree Outside Boss Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DEKU_TREE_BASEMENT_UPPER, {[]{return true;}}),
Entrance(DEKU_TREE_BOSS_ENTRYWAY, {[]{return Here(DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return HasShield;});}}),
Entrance(RR_DEKU_TREE_BASEMENT_UPPER, {[]{return true;}}),
Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, {[]{return Here(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return HasShield;});}}),
});
}
@@ -151,120 +151,120 @@ void AreaTable_Init_DekuTree() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::DekuTree.IsMQ()) {
areaTable[DEKU_TREE_MQ_LOBBY] = Area("Deku Tree MQ Lobby", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DEKU_TREE_MQ_LOBBY] = Area("Deku Tree MQ Lobby", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
}, {
//Locations
LocationAccess(DEKU_TREE_MQ_MAP_CHEST, {[]{return true;}}),
LocationAccess(DEKU_TREE_MQ_SLINGSHOT_CHEST, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, {[]{return HasFireSourceWithTorch || (IsAdult && CanUse(BOW));}}),
LocationAccess(DEKU_TREE_MQ_BASEMENT_CHEST, {[]{return HasFireSourceWithTorch || (IsAdult && CanUse(BOW));}}),
LocationAccess(DEKU_TREE_MQ_GS_LOBBY, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(RC_DEKU_TREE_MQ_MAP_CHEST, {[]{return true;}}),
LocationAccess(RC_DEKU_TREE_MQ_SLINGSHOT_CHEST, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(RC_DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST, {[]{return HasFireSourceWithTorch || (IsAdult && CanUse(RG_FAIRY_BOW));}}),
LocationAccess(RC_DEKU_TREE_MQ_BASEMENT_CHEST, {[]{return HasFireSourceWithTorch || (IsAdult && CanUse(RG_FAIRY_BOW));}}),
LocationAccess(RC_DEKU_TREE_MQ_GS_LOBBY, {[]{return IsAdult || CanChildAttack;}}),
}, {
//Exits
Entrance(DEKU_TREE_ENTRYWAY, {[]{return true;}}),
Entrance(DEKU_TREE_MQ_COMPASS_ROOM, {[]{return Here(DEKU_TREE_MQ_LOBBY, []{return (IsChild && CanUse(SLINGSHOT)) || (IsAdult && CanUse(BOW));}) &&
Here(DEKU_TREE_MQ_LOBBY, []{return HasFireSourceWithTorch || (IsAdult && CanUse(BOW));});}}),
Entrance(DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, {[]{return Here(DEKU_TREE_MQ_LOBBY, []{return (IsChild && CanUse(SLINGSHOT)) || (IsAdult && CanUse(BOW));}) &&
Here(DEKU_TREE_MQ_LOBBY, []{return HasFireSourceWithTorch;});}}),
Entrance(DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return LogicDekuB1Skip || Here(DEKU_TREE_MQ_LOBBY, []{return IsAdult;});}}),
Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_DEKU_TREE_MQ_COMPASS_ROOM, {[]{return Here(RR_DEKU_TREE_MQ_LOBBY, []{return (IsChild && CanUse(RG_FAIRY_SLINGSHOT)) || (IsAdult && CanUse(RG_FAIRY_BOW));}) &&
Here(RR_DEKU_TREE_MQ_LOBBY, []{return HasFireSourceWithTorch || (IsAdult && CanUse(RG_FAIRY_BOW));});}}),
Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, {[]{return Here(RR_DEKU_TREE_MQ_LOBBY, []{return (IsChild && CanUse(RG_FAIRY_SLINGSHOT)) || (IsAdult && CanUse(RG_FAIRY_BOW));}) &&
Here(RR_DEKU_TREE_MQ_LOBBY, []{return HasFireSourceWithTorch;});}}),
Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return LogicDekuB1Skip || Here(RR_DEKU_TREE_MQ_LOBBY, []{return IsAdult;});}}),
});
areaTable[DEKU_TREE_MQ_COMPASS_ROOM] = Area("Deku Tree MQ Compass Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DEKU_TREE_MQ_COMPASS_ROOM] = Area("Deku Tree MQ Compass Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DEKU_TREE_MQ_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(DEKU_TREE_MQ_GS_COMPASS_ROOM, {[]{return HookshotOrBoomerang &&
Here(DEKU_TREE_MQ_COMPASS_ROOM, []{return HasBombchus ||
LocationAccess(RC_DEKU_TREE_MQ_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(RC_DEKU_TREE_MQ_GS_COMPASS_ROOM, {[]{return HookshotOrBoomerang &&
Here(RR_DEKU_TREE_MQ_COMPASS_ROOM, []{return HasBombchus ||
(Bombs && (CanPlay(SongOfTime) || IsAdult)) ||
(IsAdult && CanUse(MEGATON_HAMMER) && (CanPlay(SongOfTime) || LogicDekuMQCompassGS));});}}),
(IsAdult && CanUse(RG_MEGATON_HAMMER) && (CanPlay(SongOfTime) || LogicDekuMQCompassGS));});}}),
}, {
//Exits
Entrance(DEKU_TREE_MQ_LOBBY, {[]{return true;}}),
Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return true;}}),
});
areaTable[DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT] = Area("Deku Tree MQ Basement Water Room Front", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT] = Area("Deku Tree MQ Basement Water Room Front", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, {[]{return true;}}),
LocationAccess(RC_DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return LogicDekuMQLog || (IsChild && (DekuShield || HylianShield)) ||
(IsAdult && (CanUse(LONGSHOT) || (CanUse(HOOKSHOT) && CanUse(IRON_BOOTS))));}}),
Entrance(DEKU_TREE_MQ_LOBBY, {[]{return true;}}),
Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return LogicDekuMQLog || (IsChild && (DekuShield || HylianShield)) ||
(IsAdult && (CanUse(RG_LONGSHOT) || (CanUse(RG_HOOKSHOT) && CanUse(RG_IRON_BOOTS))));}}),
Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return true;}}),
});
areaTable[DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK] = Area("Deku Tree MQ Basement Water Room Front", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK] = Area("Deku Tree MQ Basement Water Room Front", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, {[]{return CanPlay(SongOfTime);}}),
LocationAccess(RC_DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST, {[]{return CanPlay(SongOfTime);}}),
}, {
//Exits
Entrance(DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return Here(DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, []{return (IsChild && CanUse(STICKS)) || CanUse(DINS_FIRE) ||
Here(DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, []{return IsAdult && CanUse(FIRE_ARROWS);});}) &&
Here(DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, []{return IsAdult || KokiriSword || CanUseProjectile || (Nuts && Sticks);});}}),
Entrance(DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, {[]{return true;}}),
Entrance(RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return Here(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, []{return (IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) ||
Here(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, []{return IsAdult && CanUse(RG_FIRE_ARROWS);});}) &&
Here(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, []{return IsAdult || KokiriSword || CanUseProjectile || (Nuts && Sticks);});}}),
Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT, {[]{return true;}}),
});
areaTable[DEKU_TREE_MQ_BASEMENT_BACK_ROOM] = Area("Deku Tree MQ Basement Back Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM] = Area("Deku Tree MQ Basement Back Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, {[]{return (IsAdult && CanUse(LONGSHOT)) || (CanPlay(SongOfTime) && HookshotOrBoomerang);}}),
LocationAccess(DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, {[]{return HasFireSourceWithTorch && HookshotOrBoomerang;}}),
LocationAccess(RC_DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM, {[]{return (IsAdult && CanUse(RG_LONGSHOT)) || (CanPlay(SongOfTime) && HookshotOrBoomerang);}}),
LocationAccess(RC_DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM, {[]{return HasFireSourceWithTorch && HookshotOrBoomerang;}}),
}, {
//Exits
Entrance(DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return IsChild;}}),
Entrance(DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return (IsChild && CanUse(KOKIRI_SWORD)) || CanUseProjectile || (Nuts && (IsChild && CanUse(STICKS)));}}),
Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, {[]{return IsChild;}}),
Entrance(RR_DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK, {[]{return (IsChild && CanUse(RG_KOKIRI_SWORD)) || CanUseProjectile || (Nuts && (IsChild && CanUse(RG_STICKS)));}}),
});
areaTable[DEKU_TREE_MQ_BASEMENT_LEDGE] = Area("Deku Tree MQ Basement Ledge", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DEKU_TREE_MQ_BASEMENT_LEDGE] = Area("Deku Tree MQ Basement Ledge", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DEKU_TREE_MQ_DEKU_SCRUB, {[]{return CanStunDeku;}}),
LocationAccess(RC_DEKU_TREE_MQ_DEKU_SCRUB, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return IsChild;}}),
Entrance(DEKU_TREE_MQ_LOBBY, {[]{return true;}}),
Entrance(DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM,
{ [] { return Here(DEKU_TREE_MQ_BASEMENT_LEDGE, [] { return HasFireSourceWithTorch; }); } }),
Entrance(RR_DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return IsChild;}}),
Entrance(RR_DEKU_TREE_MQ_LOBBY, {[]{return true;}}),
Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM,
{ [] { return Here(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, [] { return HasFireSourceWithTorch; }); } }),
});
areaTable[DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM] =
Area("Deku Tree MQ Outside Boss Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM] =
Area("Deku Tree MQ Outside Boss Room", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(DEKU_TREE_MQ_BASEMENT_LEDGE, { [] { return true; } }),
Entrance(DEKU_TREE_BOSS_ENTRYWAY,
{ [] { return Here(DEKU_TREE_MQ_BASEMENT_LEDGE, [] { return HasShield; }); } }),
Entrance(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, { [] { return true; } }),
Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY,
{ [] { return Here(RR_DEKU_TREE_MQ_BASEMENT_LEDGE, [] { return HasShield; }); } }),
});
}
/*---------------------------
| BOSS ROOM |
---------------------------*/
areaTable[DEKU_TREE_BOSS_ENTRYWAY] =
Area("Deku Tree Boss Entryway", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_DEKU_TREE_BOSS_ENTRYWAY] =
Area("Deku Tree Boss Entryway", "Deku Tree", RHT_DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, { [] { return Dungeon::DekuTree.IsVanilla(); } }),
Entrance(DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, { [] { return Dungeon::DekuTree.IsMQ(); } }),
Entrance(DEKU_TREE_BOSS_ROOM, { [] { return true; } }),
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, { [] { return Dungeon::DekuTree.IsVanilla(); } }),
Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, { [] { return Dungeon::DekuTree.IsMQ(); } }),
Entrance(RR_DEKU_TREE_BOSS_ROOM, { [] { return true; } }),
});
areaTable[DEKU_TREE_BOSS_ROOM] =
Area("Deku Tree Boss Room", "Deku Tree", NONE, NO_DAY_NIGHT_CYCLE,
areaTable[RR_DEKU_TREE_BOSS_ROOM] =
Area("Deku Tree Boss Room", "Deku Tree", RHT_NONE, NO_DAY_NIGHT_CYCLE,
{
// Events
EventAccess(&DekuTreeClear, { [] {
return DekuTreeClear || (HasBossSoul(GOHMA_BOSS_SOUL) &&
(CanJumpslash && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) ||
return DekuTreeClear || (HasBossSoul(RG_GOHMA_SOUL) &&
(CanJumpslash && (Nuts || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) ||
HookshotOrBoomerang)));
}}),
},
{
// Locations
LocationAccess(QUEEN_GOHMA, { [] { return DekuTreeClear; } }),
LocationAccess(DEKU_TREE_QUEEN_GOHMA_HEART, { [] { return DekuTreeClear; } }),
LocationAccess(RC_QUEEN_GOHMA, { [] { return DekuTreeClear; } }),
LocationAccess(RC_DEKU_TREE_QUEEN_GOHMA_HEART, { [] { return DekuTreeClear; } }),
},
{
// Exits
Entrance(DEKU_TREE_BOSS_ENTRYWAY, { [] { return true; } }),
Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, { [] { return true; } }),
});
}

View File

@@ -10,197 +10,197 @@ void AreaTable_Init_DodongosCavern() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[DODONGOS_CAVERN_ENTRYWAY] = Area("Dodongos Cavern Entryway", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_ENTRYWAY] = Area("Dodongos Cavern Entryway", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_BEGINNING, {[]{return Dungeon::DodongosCavern.IsVanilla();}}),
Entrance(DODONGOS_CAVERN_MQ_BEGINNING, {[]{return Dungeon::DodongosCavern.IsMQ();}}),
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_BEGINNING, {[]{return Dungeon::DodongosCavern.IsVanilla();}}),
Entrance(RR_DODONGOS_CAVERN_MQ_BEGINNING, {[]{return Dungeon::DodongosCavern.IsMQ();}}),
Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::DodongosCavern.IsVanilla()) {
areaTable[DODONGOS_CAVERN_BEGINNING] = Area("Dodongos Cavern Beginning", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_BEGINNING] = Area("Dodongos Cavern Beginning", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_ENTRYWAY, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_LOBBY, {[]{return Here(DODONGOS_CAVERN_BEGINNING, []{return CanBlastOrSmash || GoronBracelet;});}}),
Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return Here(RR_DODONGOS_CAVERN_BEGINNING, []{return CanBlastOrSmash || GoronBracelet;});}}),
});
areaTable[DODONGOS_CAVERN_LOBBY] = Area("Dodongos Cavern Lobby", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DODONGOS_CAVERN_LOBBY] = Area("Dodongos Cavern Lobby", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || (CanSummonGossipFairy && Here(DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;}));}}),
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || (CanSummonGossipFairy && Here(RR_DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;}));}}),
}, {
//Locations
LocationAccess(DODONGOS_CAVERN_MAP_CHEST, {[]{return Here(DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;});}}),
LocationAccess(DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, {[]{return CanStunDeku || GoronBracelet;}}),
LocationAccess(DODONGOS_CAVERN_GOSSIP_STONE, {[]{return Here(DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;});}}),
LocationAccess(RC_DODONGOS_CAVERN_MAP_CHEST, {[]{return Here(RR_DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;});}}),
LocationAccess(RC_DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, {[]{return CanStunDeku || GoronBracelet;}}),
LocationAccess(RC_DODONGOS_CAVERN_GOSSIP_STONE, {[]{return Here(RR_DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;});}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_BEGINNING, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_LOBBY_SWITCH, {[]{return IsAdult;}}),
Entrance(DODONGOS_CAVERN_SE_CORRIDOR, {[]{return Here(DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;});}}),
Entrance(DODONGOS_CAVERN_STAIRS_LOWER, {[]{return HasAccessTo(DODONGOS_CAVERN_LOBBY_SWITCH);}}),
Entrance(DODONGOS_CAVERN_FAR_BRIDGE, {[]{return HasAccessTo(DODONGOS_CAVERN_FAR_BRIDGE);}}),
Entrance(DODONGOS_CAVERN_BOSS_AREA, {[]{return Here(DODONGOS_CAVERN_FAR_BRIDGE, []{return HasExplosives;});}}),
Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY,{[]{return false;}}),
Entrance(RR_DODONGOS_CAVERN_BEGINNING, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_LOBBY_SWITCH, {[]{return IsAdult;}}),
Entrance(RR_DODONGOS_CAVERN_SE_CORRIDOR, {[]{return Here(RR_DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;});}}),
Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, {[]{return HasAccessTo(RR_DODONGOS_CAVERN_LOBBY_SWITCH);}}),
Entrance(RR_DODONGOS_CAVERN_FAR_BRIDGE, {[]{return HasAccessTo(RR_DODONGOS_CAVERN_FAR_BRIDGE);}}),
Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, {[]{return Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return HasExplosives;});}}),
Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY,{[]{return false;}}),
});
areaTable[DODONGOS_CAVERN_LOBBY_SWITCH] = Area("Dodongos Cavern Lobby Switch", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_LOBBY_SWITCH] = Area("Dodongos Cavern Lobby Switch", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_DODONGO_ROOM, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_DODONGO_ROOM, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_SE_CORRIDOR] = Area("Dodongos Cavern SE Corridor", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_SE_CORRIDOR] = Area("Dodongos Cavern SE Corridor", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_GS_SCARECROW, {[]{return CanUse(SCARECROW) || (IsAdult && CanUse(LONGSHOT)) || (LogicDCScarecrowGS && (IsAdult || CanChildAttack));}}),
LocationAccess(RC_DODONGOS_CAVERN_GS_SCARECROW, {[]{return CanUse(RG_SCARECROW) || (IsAdult && CanUse(RG_LONGSHOT)) || (LogicDCScarecrowGS && (IsAdult || CanChildAttack));}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_SE_ROOM, {[]{return Here(DODONGOS_CAVERN_SE_CORRIDOR, []{return CanBlastOrSmash || IsAdult || CanChildAttack || (CanTakeDamage && CanShield);});}}),
Entrance(DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_SE_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_SE_CORRIDOR, []{return CanBlastOrSmash || IsAdult || CanChildAttack || (CanTakeDamage && CanShield);});}}),
Entrance(RR_DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_SE_ROOM] = Area("Dodongos Cavern SE Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_SE_ROOM] = Area("Dodongos Cavern SE Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, {[]{return IsAdult || CanChildAttack;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_SE_CORRIDOR, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_SE_CORRIDOR, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS] = Area("Dodongos Cavern Near Lower Lizalfos", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS] = Area("Dodongos Cavern Near Lower Lizalfos", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_SE_CORRIDOR, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_LOWER_LIZALFOS, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_SE_CORRIDOR, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_LOWER_LIZALFOS] = Area("Dodongos Cavern Lower Lizalfos", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_LOWER_LIZALFOS] = Area("Dodongos Cavern Lower Lizalfos", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, {[]{return Here(DODONGOS_CAVERN_LOWER_LIZALFOS, []{return IsAdult || Slingshot || Sticks || KokiriSword || HasExplosives;});}}),
Entrance(DODONGOS_CAVERN_DODONGO_ROOM, {[]{return Here(DODONGOS_CAVERN_LOWER_LIZALFOS, []{return IsAdult || Slingshot || Sticks || KokiriSword || HasExplosives;});}}),
Entrance(RR_DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS, {[]{return Here(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, []{return IsAdult || Slingshot || Sticks || KokiriSword || HasExplosives;});}}),
Entrance(RR_DODONGOS_CAVERN_DODONGO_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, []{return IsAdult || Slingshot || Sticks || KokiriSword || HasExplosives;});}}),
});
areaTable[DODONGOS_CAVERN_DODONGO_ROOM] = Area("Dodongos Cavern Dodongo Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_DODONGO_ROOM] = Area("Dodongos Cavern Dodongo Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_LOBBY_SWITCH, {[]{return HasFireSourceWithTorch;}}),
Entrance(DODONGOS_CAVERN_LOWER_LIZALFOS, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_NEAR_DODONGO_ROOM, {[]{return Here(DODONGOS_CAVERN_DODONGO_ROOM, []{return CanBlastOrSmash || GoronBracelet;});}}),
Entrance(RR_DODONGOS_CAVERN_LOBBY_SWITCH, {[]{return HasFireSourceWithTorch;}}),
Entrance(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_NEAR_DODONGO_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_DODONGO_ROOM, []{return CanBlastOrSmash || GoronBracelet;});}}),
});
areaTable[DODONGOS_CAVERN_NEAR_DODONGO_ROOM] = Area("Dodongos Cavern Near Dodongo Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_NEAR_DODONGO_ROOM] = Area("Dodongos Cavern Near Dodongo Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, {[]{return CanStunDeku;}}),
LocationAccess(RC_DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_DODONGO_ROOM, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_DODONGO_ROOM, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_STAIRS_LOWER] = Area("Dodongos Cavern Stairs Lower", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_STAIRS_LOWER] = Area("Dodongos Cavern Stairs Lower", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_STAIRS_UPPER, {[]{return HasExplosives || GoronBracelet || CanUse(DINS_FIRE) || (LogicDCStaircase && CanUse(BOW));}}),
Entrance(DODONGOS_CAVERN_COMPASS_ROOM, {[]{return Here(DODONGOS_CAVERN_STAIRS_LOWER, []{return CanBlastOrSmash || GoronBracelet;});}}),
Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_STAIRS_UPPER, {[]{return HasExplosives || GoronBracelet || CanUse(RG_DINS_FIRE) || (LogicDCStaircase && CanUse(RG_FAIRY_BOW));}}),
Entrance(RR_DODONGOS_CAVERN_COMPASS_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_STAIRS_LOWER, []{return CanBlastOrSmash || GoronBracelet;});}}),
});
areaTable[DODONGOS_CAVERN_STAIRS_UPPER] = Area("Dodongos Cavern Stairs Upper", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_STAIRS_UPPER] = Area("Dodongos Cavern Stairs Upper", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, {[]{return Here(DODONGOS_CAVERN_FAR_BRIDGE, []{return HookshotOrBoomerang;}) || CanUse(LONGSHOT);}}),
LocationAccess(DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, {[]{return IsAdult || CanChildAttack || (HasAccessTo(DODONGOS_CAVERN_STAIRS_LOWER) && CanUse(LONGSHOT) && LogicDCVinesGS);}}),
LocationAccess(RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, {[]{return Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return HookshotOrBoomerang;}) || CanUse(RG_LONGSHOT);}}),
LocationAccess(RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, {[]{return IsAdult || CanChildAttack || (HasAccessTo(RR_DODONGOS_CAVERN_STAIRS_LOWER) && CanUse(RG_LONGSHOT) && LogicDCVinesGS);}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_STAIRS_LOWER, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_ARMOS_ROOM, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_ARMOS_ROOM, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_COMPASS_ROOM] = Area("Dodongos Cavern Compass Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_COMPASS_ROOM] = Area("Dodongos Cavern Compass Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(RC_DODONGOS_CAVERN_COMPASS_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_STAIRS_LOWER, {[]{return IsAdult || HasExplosives || GoronBracelet;}}),
Entrance(RR_DODONGOS_CAVERN_STAIRS_LOWER, {[]{return IsAdult || HasExplosives || GoronBracelet;}}),
});
areaTable[DODONGOS_CAVERN_ARMOS_ROOM] = Area("Dodongos Cavern Armos Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_ARMOS_ROOM] = Area("Dodongos Cavern Armos Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_STAIRS_UPPER, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_STAIRS_UPPER, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_BOMB_ROOM_LOWER] = Area("Dodongos Cavern Bomb Room Lower", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER] = Area("Dodongos Cavern Bomb Room Lower", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, {[]{return true;}}),
LocationAccess(RC_DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_2F_SIDE_ROOM, {[]{return Here(DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || (LogicDCScrubRoom && GoronBracelet);});}}),
Entrance(DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, {[]{return Here(DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || GoronBracelet;});}}),
Entrance(DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return (IsAdult && LogicDCJump) || CanUse(HOVER_BOOTS) || (IsAdult && CanUse(LONGSHOT));}}),
Entrance(RR_DODONGOS_CAVERN_2F_SIDE_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || (LogicDCScrubRoom && GoronBracelet);});}}),
Entrance(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || GoronBracelet;});}}),
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return (IsAdult && LogicDCJump) || CanUse(RG_HOVER_BOOTS) || (IsAdult && CanUse(RG_LONGSHOT));}}),
});
areaTable[DODONGOS_CAVERN_2F_SIDE_ROOM] = Area("Dodongos Cavern 2F Side Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_2F_SIDE_ROOM] = Area("Dodongos Cavern 2F Side Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(RC_DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM] = Area("Dodongos Cavern First Slingshot Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM] = Area("Dodongos Cavern First Slingshot Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return CanUse(SLINGSHOT) || CanUse(BOW) || LogicDCSlingshotSkip;}}),
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || LogicDCSlingshotSkip;}}),
});
areaTable[DODONGOS_CAVERN_UPPER_LIZALFOS] = Area("Dodongos Cavern Upper Lizalfos", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_UPPER_LIZALFOS] = Area("Dodongos Cavern Upper Lizalfos", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_LOWER_LIZALFOS, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, {[]{return Here(DODONGOS_CAVERN_LOWER_LIZALFOS, []{return IsAdult || Slingshot || Sticks || KokiriSword || HasExplosives;});}}),
Entrance(DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, {[]{return Here(DODONGOS_CAVERN_LOWER_LIZALFOS, []{return IsAdult || Slingshot || Sticks || KokiriSword || HasExplosives;});}}),
Entrance(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, []{return IsAdult || Slingshot || Sticks || KokiriSword || HasExplosives;});}}),
Entrance(RR_DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_LOWER_LIZALFOS, []{return IsAdult || Slingshot || Sticks || KokiriSword || HasExplosives;});}}),
});
areaTable[DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM] = Area("Dodongos Cavern Second Slingshot Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM] = Area("Dodongos Cavern Second Slingshot Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return CanUse(SLINGSHOT) || CanUse(BOW) || LogicDCSlingshotSkip;}}),
Entrance(RR_DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW) || LogicDCSlingshotSkip;}}),
});
areaTable[DODONGOS_CAVERN_BOMB_ROOM_UPPER] = Area("Dodongos Cavern Bomb Room Upper", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER] = Area("Dodongos Cavern Bomb Room Upper", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_BOMB_BAG_CHEST, {[]{return true;}}),
LocationAccess(RC_DODONGOS_CAVERN_BOMB_BAG_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_FAR_BRIDGE, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_FAR_BRIDGE, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_FAR_BRIDGE] = Area("Dodongos Cavern Far Bridge", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_FAR_BRIDGE] = Area("Dodongos Cavern Far Bridge", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, {[]{return Here(DODONGOS_CAVERN_FAR_BRIDGE, []{return CanBlastOrSmash;});}}),
LocationAccess(RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, {[]{return Here(RR_DODONGOS_CAVERN_FAR_BRIDGE, []{return CanBlastOrSmash;});}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_BOSS_AREA] = Area("Dodongos Cavern Boss Area", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DODONGOS_CAVERN_BOSS_AREA] = Area("Dodongos Cavern Boss Area", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_BACK_ROOM, {[]{return Here(DODONGOS_CAVERN_BOSS_AREA, []{return CanBlastOrSmash;});}}),
Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_BACK_ROOM, {[]{return Here(RR_DODONGOS_CAVERN_BOSS_AREA, []{return CanBlastOrSmash;});}}),
Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_BACK_ROOM] = Area("Dodongos Cavern Back Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_BACK_ROOM] = Area("Dodongos Cavern Back Room", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_GS_BACK_ROOM, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(RC_DODONGOS_CAVERN_GS_BACK_ROOM, {[]{return IsAdult || CanChildAttack;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_BOSS_AREA, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, {[]{return true;}}),
});
}
@@ -208,102 +208,102 @@ void AreaTable_Init_DodongosCavern() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::DodongosCavern.IsMQ()) {
areaTable[DODONGOS_CAVERN_MQ_BEGINNING] = Area("Dodongos Cavern MQ Beginning", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_DODONGOS_CAVERN_MQ_BEGINNING] = Area("Dodongos Cavern MQ Beginning", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DODONGOS_CAVERN_ENTRYWAY, {[]{return true;}}),
Entrance(DODONGOS_CAVERN_MQ_LOBBY, {[]{return Here(DODONGOS_CAVERN_MQ_BEGINNING, []{return CanBlastOrSmash || GoronBracelet;});}}),
Entrance(RR_DODONGOS_CAVERN_ENTRYWAY, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_MQ_LOBBY, {[]{return Here(RR_DODONGOS_CAVERN_MQ_BEGINNING, []{return CanBlastOrSmash || GoronBracelet;});}}),
});
areaTable[DODONGOS_CAVERN_MQ_LOBBY] = Area("Dodongos Cavern MQ Lobby", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DODONGOS_CAVERN_MQ_LOBBY] = Area("Dodongos Cavern MQ Lobby", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
}, {
//Locations
LocationAccess(DODONGOS_CAVERN_MQ_MAP_CHEST, {[]{return true;}}),
LocationAccess(DODONGOS_CAVERN_MQ_COMPASS_CHEST, {[]{return IsAdult || CanChildAttack || Nuts;}}),
LocationAccess(DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, {[]{return (IsChild && CanUse(STICKS)) || HasFireSource;}}),
LocationAccess(DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, {[]{return CanBlastOrSmash || (IsChild && CanUse(STICKS)) || CanUse(DINS_FIRE) || (IsAdult && (LogicDCJump || HoverBoots || Hookshot));}}),
LocationAccess(DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, {[]{return CanPlay(SongOfTime) && (CanChildAttack || IsAdult);}}),
LocationAccess(DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, {[]{return (IsChild && CanUse(STICKS)) || HasFireSource;}}),
LocationAccess(DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, {[]{return CanBlastOrSmash;}}),
LocationAccess(DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, {[]{return CanStunDeku;}}),
LocationAccess(DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, {[]{return CanStunDeku;}}),
LocationAccess(DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, {[]{return CanStunDeku;}}),
LocationAccess(DODONGOS_CAVERN_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_MAP_CHEST, {[]{return true;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_COMPASS_CHEST, {[]{return IsAdult || CanChildAttack || Nuts;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST, {[]{return (IsChild && CanUse(RG_STICKS)) || HasFireSource;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST, {[]{return CanBlastOrSmash || (IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) || (IsAdult && (LogicDCJump || HoverBoots || Hookshot));}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM, {[]{return CanPlay(SongOfTime) && (CanChildAttack || IsAdult);}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM, {[]{return (IsChild && CanUse(RG_STICKS)) || HasFireSource;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM, {[]{return CanBlastOrSmash;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR, {[]{return CanStunDeku;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, {[]{return CanStunDeku;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, {[]{return CanStunDeku;}}),
LocationAccess(RC_DODONGOS_CAVERN_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return Here(DODONGOS_CAVERN_MQ_LOBBY, []{return CanBlastOrSmash || (((IsChild && CanUse(STICKS)) || CanUse(DINS_FIRE)) && CanTakeDamage);});}}),
Entrance(DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return IsAdult || (Here(DODONGOS_CAVERN_MQ_LOBBY, []{return IsAdult;}) && HasExplosives) || (LogicDCMQChildBombs && CanJumpslash && CanTakeDamage);}}),
Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return CanBlastOrSmash || (((IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE)) && CanTakeDamage);});}}),
Entrance(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return IsAdult || (Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return IsAdult;}) && HasExplosives) || (LogicDCMQChildBombs && CanJumpslash && CanTakeDamage);}}),
//Trick: IsAdult || HasExplosives || (LogicDCMQChildBombs && (KokiriSword || Sticks) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
Entrance(DODONGOS_CAVERN_MQ_BOSS_AREA, {[]{return HasExplosives || (GoronBracelet && ((IsAdult && LogicDCMQEyesAdult) || (IsChild && LogicDCMQEyesChild)) && ((IsChild && (CanUse(STICKS))) || CanUse(DINS_FIRE) || (IsAdult && (LogicDCJump || Hammer || HoverBoots || Hookshot))));}}),
//Trick: HasExplosives || (LogicDCMQEyes && GoronBracelet && (IsAdult || LogicDCMQChildBack) && ((IsChild && CanUse(STICKS)) || CanUse(DINS_FIRE) || (IsAdult && (LogicDCJump || Hammer || HoverBoots || Hookshot))))
Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, {[]{return HasExplosives || (GoronBracelet && ((IsAdult && LogicDCMQEyesAdult) || (IsChild && LogicDCMQEyesChild)) && ((IsChild && (CanUse(RG_STICKS))) || CanUse(RG_DINS_FIRE) || (IsAdult && (LogicDCJump || Hammer || HoverBoots || Hookshot))));}}),
//Trick: HasExplosives || (LogicDCMQEyes && GoronBracelet && (IsAdult || LogicDCMQChildBack) && ((IsChild && CanUse(RG_STICKS)) || CanUse(RG_DINS_FIRE) || (IsAdult && (LogicDCJump || Hammer || HoverBoots || Hookshot))))
});
areaTable[DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE] = Area("Dodongos Cavern MQ Lower Right Side", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE] = Area("Dodongos Cavern MQ Lower Right Side", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, {[]{return CanStunDeku;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return (Here(DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, []{return IsAdult && CanUse(BOW);}) || GoronBracelet ||
CanUse(DINS_FIRE) || HasExplosives) &&
IsChild && CanUse(SLINGSHOT);}}),
Entrance(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, {[]{return (Here(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, []{return IsAdult && CanUse(RG_FAIRY_BOW);}) || GoronBracelet ||
CanUse(RG_DINS_FIRE) || HasExplosives) &&
IsChild && CanUse(RG_FAIRY_SLINGSHOT);}}),
});
areaTable[DODONGOS_CAVERN_MQ_BOMB_BAG_AREA] = Area("Dodongos Cavern MQ Bomb Bag Area", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA] = Area("Dodongos Cavern MQ Bomb Bag Area", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, {[]{return true;}}),
LocationAccess(DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, {[]{return (Here(DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, []{return IsAdult && CanUse(BOW);}) || GoronBracelet || CanUse(DINS_FIRE) || HasExplosives) && HookshotOrBoomerang;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST, {[]{return true;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM, {[]{return (Here(RR_DODONGOS_CAVERN_MQ_BOMB_BAG_AREA, []{return IsAdult && CanUse(RG_FAIRY_BOW);}) || GoronBracelet || CanUse(RG_DINS_FIRE) || HasExplosives) && HookshotOrBoomerang;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE, {[]{return true;}}),
});
areaTable[DODONGOS_CAVERN_MQ_BOSS_AREA] = Area("Dodongos Cavern MQ BossArea", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_DODONGOS_CAVERN_MQ_BOSS_AREA] = Area("Dodongos Cavern MQ BossArea", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, {[]{return true;}}),
LocationAccess(DODONGOS_CAVERN_MQ_GS_BACK_AREA, {[]{return true;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, {[]{return true;}}),
LocationAccess(RC_DODONGOS_CAVERN_MQ_GS_BACK_AREA, {[]{return true;}}),
}, {
//Exits
Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY, {[]{return true;}}),
Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, {[]{return true;}}),
});
}
/*---------------------------
| BOSS ROOM |
---------------------------*/
areaTable[DODONGOS_CAVERN_BOSS_ENTRYWAY] =
Area("Dodongos Cavern Boss Entryway", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_DODONGOS_CAVERN_BOSS_ENTRYWAY] =
Area("Dodongos Cavern Boss Entryway", "Dodongos Cavern", RHT_DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(DODONGOS_CAVERN_BOSS_AREA, { [] { return Dungeon::DodongosCavern.IsVanilla(); } }),
Entrance(DODONGOS_CAVERN_MQ_BOSS_AREA, { [] { return Dungeon::DodongosCavern.IsMQ(); } }),
Entrance(DODONGOS_CAVERN_BOSS_ROOM, { [] { return true; } }),
Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, { [] { return Dungeon::DodongosCavern.IsVanilla(); } }),
Entrance(RR_DODONGOS_CAVERN_MQ_BOSS_AREA, { [] { return Dungeon::DodongosCavern.IsMQ(); } }),
Entrance(RR_DODONGOS_CAVERN_BOSS_ROOM, { [] { return true; } }),
});
areaTable[DODONGOS_CAVERN_BOSS_ROOM] =
Area("Dodongos Cavern Boss Room", "Dodongos Cavern", NONE, NO_DAY_NIGHT_CYCLE,
areaTable[RR_DODONGOS_CAVERN_BOSS_ROOM] =
Area("Dodongos Cavern Boss Room", "Dodongos Cavern", RHT_NONE, NO_DAY_NIGHT_CYCLE,
{
// Events
EventAccess(&DodongosCavernClear,
{ [] {
return DodongosCavernClear || (HasBossSoul(KING_DODONGO_BOSS_SOUL) &&
(Here(DODONGOS_CAVERN_BOSS_ROOM,
[] { return HasExplosives || (CanUse(MEGATON_HAMMER) && LogicDCHammerFloor); }) &&
return DodongosCavernClear || (HasBossSoul(RG_KING_DODONGO_SOUL) &&
(Here(RR_DODONGOS_CAVERN_BOSS_ROOM,
[] { return HasExplosives || (CanUse(RG_MEGATON_HAMMER) && LogicDCHammerFloor); }) &&
(Bombs || GoronBracelet) && CanJumpslash)); /*todo add chu kill to tricks*/
}}),
},
{
// Locations
LocationAccess(DODONGOS_CAVERN_BOSS_ROOM_CHEST, { [] { return true; } }),
LocationAccess(DODONGOS_CAVERN_KING_DODONGO_HEART, { [] { return DodongosCavernClear; } }),
LocationAccess(KING_DODONGO, { [] { return DodongosCavernClear; } }),
LocationAccess(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, { [] { return true; } }),
LocationAccess(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, { [] { return DodongosCavernClear; } }),
LocationAccess(RC_KING_DODONGO, { [] { return DodongosCavernClear; } }),
},
{
// Exits
Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY, { [] { return true; } }),
Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, { [] { return true; } }),
});
}

View File

@@ -10,301 +10,301 @@ void AreaTable_Init_FireTemple() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[FIRE_TEMPLE_ENTRYWAY] = Area("Fire Temple Entryway", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_ENTRYWAY] = Area("Fire Temple Entryway", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return Dungeon::FireTemple.IsVanilla();}}),
Entrance(FIRE_TEMPLE_MQ_LOWER, {[]{return Dungeon::FireTemple.IsMQ();}}),
Entrance(DMC_CENTRAL_LOCAL, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return Dungeon::FireTemple.IsVanilla();}}),
Entrance(RR_FIRE_TEMPLE_MQ_LOWER, {[]{return Dungeon::FireTemple.IsMQ();}}),
Entrance(RR_DMC_CENTRAL_LOCAL, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::FireTemple.IsVanilla()) {
areaTable[FIRE_TEMPLE_FIRST_ROOM] = Area("Fire Temple First Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_FIRST_ROOM] = Area("Fire Temple First Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
}, {
//Exits
Entrance(FIRE_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(FIRE_TEMPLE_NEAR_BOSS_ROOM, {[]{return FireTimer >= 24;}}),
Entrance(FIRE_TEMPLE_LOOP_ENEMIES, {[]{return Here(FIRE_TEMPLE_FIRST_ROOM, []{return CanUse(MEGATON_HAMMER);}) && (SmallKeys(FIRE_TEMPLE, 8) || !IsKeysanity);}}),
Entrance(FIRE_TEMPLE_LOOP_EXIT, {[]{return true;}}),
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 2) && FireTimer >= 24;}}),
Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, {[]{return FireTimer >= 24;}}),
Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, {[]{return Here(RR_FIRE_TEMPLE_FIRST_ROOM, []{return CanUse(RG_MEGATON_HAMMER);}) && (SmallKeys(RR_FIRE_TEMPLE, 8) || !IsKeysanity);}}),
Entrance(RR_FIRE_TEMPLE_LOOP_EXIT, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 2) && FireTimer >= 24;}}),
});
areaTable[FIRE_TEMPLE_NEAR_BOSS_ROOM] = Area("Fire Temple Near Boss Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FIRE_TEMPLE_NEAR_BOSS_ROOM] = Area("Fire Temple Near Boss Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return FairyPot || (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT));}}),
EventAccess(&FairyPot, {[]{return FairyPot || (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
}, {
//Locations
LocationAccess(FIRE_TEMPLE_NEAR_BOSS_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_NEAR_BOSS_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}),
Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && LogicFireBossDoorJump) || CanUse(HOVER_BOOTS) || Here(FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(MEGATON_HAMMER);}));}}),
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyFireTemple && ((IsAdult && LogicFireBossDoorJump) || CanUse(RG_HOVER_BOOTS) || Here(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(RG_MEGATON_HAMMER);}));}}),
});
areaTable[FIRE_TEMPLE_LOOP_ENEMIES] = Area("Fire Temple Loop Enemies", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_LOOP_ENEMIES] = Area("Fire Temple Loop Enemies", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 8) || !IsKeysanity;}}),
Entrance(FIRE_TEMPLE_LOOP_TILES, {[]{return Here(FIRE_TEMPLE_LOOP_ENEMIES, []{return IsAdult || KokiriSword;});}}),
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 8) || !IsKeysanity;}}),
Entrance(RR_FIRE_TEMPLE_LOOP_TILES, {[]{return Here(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return IsAdult || KokiriSword;});}}),
});
areaTable[FIRE_TEMPLE_LOOP_TILES] = Area("Fire Temple Loop Tiles", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_LOOP_TILES] = Area("Fire Temple Loop Tiles", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_GS_BOSS_KEY_LOOP, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP, {[]{return IsAdult || CanChildAttack;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_LOOP_ENEMIES, {[]{return true;}}),
Entrance(FIRE_TEMPLE_LOOP_FLARE_DANCER, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_LOOP_FLARE_DANCER, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_LOOP_FLARE_DANCER] = Area("Fire Temple Loop Flare Dancer", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_LOOP_FLARE_DANCER] = Area("Fire Temple Loop Flare Dancer", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_FLARE_DANCER_CHEST, {[]{return (HasExplosives || CanUse(MEGATON_HAMMER)) && IsAdult;}}),
LocationAccess(RC_FIRE_TEMPLE_FLARE_DANCER_CHEST, {[]{return (HasExplosives || CanUse(RG_MEGATON_HAMMER)) && IsAdult;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_LOOP_TILES, {[]{return true;}}),
Entrance(FIRE_TEMPLE_LOOP_HAMMER_SWITCH, {[]{return Here(FIRE_TEMPLE_LOOP_FLARE_DANCER, []{return (HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(HOOKSHOT)) && (IsAdult || KokiriSword || Slingshot || Boomerang);});}}),
Entrance(RR_FIRE_TEMPLE_LOOP_TILES, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH, {[]{return Here(RR_FIRE_TEMPLE_LOOP_FLARE_DANCER, []{return (HasExplosives || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_HOOKSHOT)) && (IsAdult || KokiriSword || Slingshot || Boomerang);});}}),
});
areaTable[FIRE_TEMPLE_LOOP_HAMMER_SWITCH] = Area("Fire Temple Loop Hammer Switch", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH] = Area("Fire Temple Loop Hammer Switch", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FireLoopSwitch, {[]{return FireLoopSwitch || CanUse(MEGATON_HAMMER);}}),
EventAccess(&FireLoopSwitch, {[]{return FireLoopSwitch || CanUse(RG_MEGATON_HAMMER);}}),
}, {}, {
//Exits
Entrance(FIRE_TEMPLE_LOOP_FLARE_DANCER, {[]{return true;}}),
Entrance(FIRE_TEMPLE_LOOP_GORON_ROOM, {[]{return FireLoopSwitch;}}),
Entrance(RR_FIRE_TEMPLE_LOOP_FLARE_DANCER, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_LOOP_GORON_ROOM, {[]{return FireLoopSwitch;}}),
});
areaTable[FIRE_TEMPLE_LOOP_GORON_ROOM] = Area("Fire Temple Loop Goron Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_LOOP_GORON_ROOM] = Area("Fire Temple Loop Goron Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_LOOP_HAMMER_SWITCH, {[]{return FireLoopSwitch;}}),
Entrance(FIRE_TEMPLE_LOOP_EXIT, {[]{return FireLoopSwitch;}}),
Entrance(RR_FIRE_TEMPLE_LOOP_HAMMER_SWITCH, {[]{return FireLoopSwitch;}}),
Entrance(RR_FIRE_TEMPLE_LOOP_EXIT, {[]{return FireLoopSwitch;}}),
});
areaTable[FIRE_TEMPLE_LOOP_EXIT] = Area("Fire Temple Loop Exit", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_LOOP_EXIT] = Area("Fire Temple Loop Exit", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}),
Entrance(FIRE_TEMPLE_LOOP_GORON_ROOM, {[]{return FireLoopSwitch;}}),
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_LOOP_GORON_ROOM, {[]{return FireLoopSwitch;}}),
});
areaTable[FIRE_TEMPLE_BIG_LAVA_ROOM] = Area("Fire Temple Big Lava Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM] = Area("Fire Temple Big Lava Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 2);}}),
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON, {[]{return true;}}),
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, {[]{return IsAdult && (CanPlay(SongOfTime) || LogicFireSongOfTime);}}),
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON, {[]{return IsAdult && HasExplosives;}}),
Entrance(FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 3);}}),
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 2);}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES, {[]{return IsAdult && (CanPlay(SongOfTime) || LogicFireSongOfTime);}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON, {[]{return IsAdult && HasExplosives;}}),
Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 3);}}),
});
areaTable[FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON] = Area("Fire Temple Big Lava Room North Goron", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON] = Area("Fire Temple Big Lava Room North Goron", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES] = Area("Fire Temple Big Lava Room North Tiles", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES] = Area("Fire Temple Big Lava Room North Tiles", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, {[]{return IsAdult;}}),
LocationAccess(RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, {[]{return IsAdult;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON] = Area("Fire Temple Big Lava Room South Goron", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON] = Area("Fire Temple Big Lava Room South Goron", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_FIRE_PILLAR_ROOM] = Area("Fire Temple Fire Pillar Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM] = Area("Fire Temple Fire Pillar Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 3);}}),
Entrance(FIRE_TEMPLE_SHORTCUT_ROOM, {[]{return FireTimer >= 56 && SmallKeys(FIRE_TEMPLE, 4);}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 3);}}),
Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, {[]{return FireTimer >= 56 && SmallKeys(RR_FIRE_TEMPLE, 4);}}),
});
areaTable[FIRE_TEMPLE_SHORTCUT_ROOM] = Area("Fire Temple Shortcut Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_SHORTCUT_ROOM] = Area("Fire Temple Shortcut Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, {[]{return Here(FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;});}}),
LocationAccess(RC_FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, {[]{return Here(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;});}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 4);}}),
Entrance(FIRE_TEMPLE_SHORTCUT_CLIMB, {[]{return Here(FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;});}}),
Entrance(FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return (GoronBracelet || (IsAdult && LogicFireStrength)) && (HasExplosives || (IsAdult && (CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(SLINGSHOT))));}}),
Entrance(RR_FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 4);}}),
Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, {[]{return Here(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;});}}),
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return (GoronBracelet || (IsAdult && LogicFireStrength)) && (HasExplosives || (IsAdult && (CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT))));}}),
});
areaTable[FIRE_TEMPLE_SHORTCUT_CLIMB] = Area("Fire Temple Shortcut Climb", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_SHORTCUT_CLIMB] = Area("Fire Temple Shortcut Climb", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_SHORTCUT_ROOM, {[]{return true;}}),
Entrance(FIRE_TEMPLE_BOULDER_MAZE_UPPER, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_BOULDER_MAZE_LOWER] = Area("Fire Temple Boulder Maze Lower", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER] = Area("Fire Temple Boulder Maze Lower", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, {[]{return true;}}),
LocationAccess(FIRE_TEMPLE_GS_BOULDER_MAZE, {[]{return HasExplosives && (IsAdult || Boomerang || CanUse(HOOKSHOT));}}),
LocationAccess(RC_FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_GS_BOULDER_MAZE, {[]{return HasExplosives && (IsAdult || Boomerang || CanUse(RG_HOOKSHOT));}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_SHORTCUT_ROOM, {[]{return true;}}),
Entrance(FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM, {[]{return true;}}),
Entrance(FIRE_TEMPLE_EAST_CENTRAL_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 5, 7);}}),
Entrance(FIRE_TEMPLE_BOULDER_MAZE_UPPER, {[]{return false;}}),
Entrance(RR_FIRE_TEMPLE_SHORTCUT_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 5, 7);}}),
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, {[]{return false;}}),
});
areaTable[FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM] = Area("Fire Temple Boulder Maze Lower Side Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM] = Area("Fire Temple Boulder Maze Lower Side Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_EAST_CENTRAL_ROOM] = Area("Fire Temple East Central Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM] = Area("Fire Temple East Central Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return CanTakeDamage;}}),
Entrance(FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return SmallKeys(FIRE_TEMPLE, 5, 8);}}),
Entrance(FIRE_TEMPLE_FIRE_WALL_CHASE, {[]{return SmallKeys(FIRE_TEMPLE, 6, 8);}}),
Entrance(FIRE_TEMPLE_MAP_AREA, {[]{return CanUse(SLINGSHOT) || CanUse(BOW);}}),
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return CanTakeDamage;}}),
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return SmallKeys(RR_FIRE_TEMPLE, 5, 8);}}),
Entrance(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, {[]{return SmallKeys(RR_FIRE_TEMPLE, 6, 8);}}),
Entrance(RR_FIRE_TEMPLE_MAP_AREA, {[]{return CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);}}),
});
areaTable[FIRE_TEMPLE_FIRE_WALL_CHASE] = Area("Fire Temple Fire Wall Chase", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_FIRE_WALL_CHASE] = Area("Fire Temple Fire Wall Chase", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_EAST_CENTRAL_ROOM, {[]{return FireTimer >= 24 && SmallKeys(FIRE_TEMPLE, 6, 8);}}),
Entrance(FIRE_TEMPLE_MAP_AREA, {[]{return IsAdult;}}),
Entrance(FIRE_TEMPLE_BOULDER_MAZE_UPPER, {[]{return FireTimer >= 24 && IsAdult;}}),
Entrance(FIRE_TEMPLE_CORRIDOR, {[]{return FireTimer >= 24 && IsAdult && SmallKeys(FIRE_TEMPLE, 7);}}),
Entrance(RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM, {[]{return FireTimer >= 24 && SmallKeys(RR_FIRE_TEMPLE, 6, 8);}}),
Entrance(RR_FIRE_TEMPLE_MAP_AREA, {[]{return IsAdult;}}),
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, {[]{return FireTimer >= 24 && IsAdult;}}),
Entrance(RR_FIRE_TEMPLE_CORRIDOR, {[]{return FireTimer >= 24 && IsAdult && SmallKeys(RR_FIRE_TEMPLE, 7);}}),
});
areaTable[FIRE_TEMPLE_MAP_AREA] = Area("Fire Temple Map Area", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_MAP_AREA] = Area("Fire Temple Map Area", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_MAP_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_MAP_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_EAST_CENTRAL_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_BOULDER_MAZE_UPPER] = Area("Fire Temple Boulder Maze Upper", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER] = Area("Fire Temple Boulder Maze Upper", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_SHORTCUT_CLIMB, {[]{return HasExplosives;}}),
Entrance(FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return true;}}),
Entrance(FIRE_TEMPLE_FIRE_WALL_CHASE, {[]{return true;}}),
Entrance(FIRE_TEMPLE_SCARECROW_ROOM, {[]{return CanUse(SCARECROW) || (LogicFireScarecrow && IsAdult && CanUse(LONGSHOT));}}),
Entrance(RR_FIRE_TEMPLE_SHORTCUT_CLIMB, {[]{return HasExplosives;}}),
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_SCARECROW_ROOM, {[]{return CanUse(RG_SCARECROW) || (LogicFireScarecrow && IsAdult && CanUse(RG_LONGSHOT));}}),
});
areaTable[FIRE_TEMPLE_SCARECROW_ROOM] = Area("Fire Temple Scarecrow Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_SCARECROW_ROOM] = Area("Fire Temple Scarecrow Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_GS_SCARECROW_CLIMB, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB, {[]{return IsAdult || CanChildAttack;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_BOULDER_MAZE_UPPER, {[]{return true;}}),
Entrance(FIRE_TEMPLE_EAST_PEAK, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BOULDER_MAZE_UPPER, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_EAST_PEAK, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_EAST_PEAK] = Area("Fire Temple East Peak", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_EAST_PEAK] = Area("Fire Temple East Peak", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_SCARECROW_CHEST, {[]{return true;}}),
LocationAccess(FIRE_TEMPLE_GS_SCARECROW_TOP, {[]{return CanUseProjectile;}}),
LocationAccess(RC_FIRE_TEMPLE_SCARECROW_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_GS_SCARECROW_TOP, {[]{return CanUseProjectile;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_SCARECROW_ROOM, {[]{return true;}}),
Entrance(FIRE_TEMPLE_EAST_CENTRAL_ROOM, {[]{return CanTakeDamage;}}),
Entrance(RR_FIRE_TEMPLE_SCARECROW_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_EAST_CENTRAL_ROOM, {[]{return CanTakeDamage;}}),
});
areaTable[FIRE_TEMPLE_CORRIDOR] = Area("Fire Temple Corridor", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_CORRIDOR] = Area("Fire Temple Corridor", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_FIRE_WALL_CHASE, {[]{return SmallKeys(FIRE_TEMPLE, 7);}}),
Entrance(FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_FIRE_WALL_CHASE, {[]{return SmallKeys(RR_FIRE_TEMPLE, 7);}}),
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_FIRE_MAZE_ROOM] = Area("Fire Temple Fire Maze Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_FIRE_MAZE_ROOM] = Area("Fire Temple Fire Maze Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_CORRIDOR, {[]{return true;}}),
Entrance(FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return CanUse(HOVER_BOOTS);}}),
Entrance(FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM, {[]{return true;}}),
Entrance(FIRE_TEMPLE_WEST_CENTRAL_LOWER, {[]{return SmallKeys(FIRE_TEMPLE, 8);}}),
Entrance(FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return LogicFireFlameMaze || false;}}),
Entrance(RR_FIRE_TEMPLE_CORRIDOR, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return CanUse(RG_HOVER_BOOTS);}}),
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER, {[]{return SmallKeys(RR_FIRE_TEMPLE, 8);}}),
Entrance(RR_FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return LogicFireFlameMaze || false;}}),
});
areaTable[FIRE_TEMPLE_FIRE_MAZE_UPPER] = Area("Fire Temple Fire Maze Upper", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_FIRE_MAZE_UPPER] = Area("Fire Temple Fire Maze Upper", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_NEAR_BOSS_ROOM, {[]{return CanUse(MEGATON_HAMMER);}}),
Entrance(FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return true;}}),
Entrance(FIRE_TEMPLE_WEST_CENTRAL_UPPER, {[]{return CanUse(MEGATON_HAMMER);}}),
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, {[]{return CanUse(RG_MEGATON_HAMMER);}}),
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, {[]{return CanUse(RG_MEGATON_HAMMER);}}),
});
areaTable[FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM] = Area("Fire Temple Fire Maze Side Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM] = Area("Fire Temple Fire Maze Side Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_COMPASS_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_WEST_CENTRAL_LOWER] = Area("Fire Temple West Central Lower", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER] = Area("Fire Temple West Central Lower", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_HIGHEST_GORON_CHEST, {[]{return Here(FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (CanPlay(SongOfTime) || LogicRustedSwitches) && CanUse(MEGATON_HAMMER);});}}),
LocationAccess(RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST, {[]{return Here(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (CanPlay(SongOfTime) || LogicRustedSwitches) && CanUse(RG_MEGATON_HAMMER);});}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 8);}}),
Entrance(FIRE_TEMPLE_WEST_CENTRAL_UPPER, {[]{return IsAdult && CanPlay(SongOfTime);}}),
Entrance(FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return SmallKeys(RR_FIRE_TEMPLE, 8);}}),
Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, {[]{return IsAdult && CanPlay(SongOfTime);}}),
Entrance(RR_FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_WEST_CENTRAL_UPPER] = Area("Fire Temple West Central Upper", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER] = Area("Fire Temple West Central Upper", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return false;}}),
Entrance(FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return true;}}),
Entrance(FIRE_TEMPLE_WEST_CENTRAL_LOWER, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return false;}}),
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER, {[]{return true;}}),
});
areaTable[FIRE_TEMPLE_LATE_FIRE_MAZE] = Area("Fire Temple Late Fire Maze", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_LATE_FIRE_MAZE] = Area("Fire Temple Late Fire Maze", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return false;}}),
Entrance(FIRE_TEMPLE_WEST_CENTRAL_LOWER, {[]{return true;}}),
Entrance(FIRE_TEMPLE_UPPER_FLARE_DANCER, {[]{return HasExplosives;}}),
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return false;}}),
Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_LOWER, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_UPPER_FLARE_DANCER, {[]{return HasExplosives;}}),
});
areaTable[FIRE_TEMPLE_UPPER_FLARE_DANCER] = Area("Fire Temple Upper Flare Dancer", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_UPPER_FLARE_DANCER] = Area("Fire Temple Upper Flare Dancer", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return Here(FIRE_TEMPLE_UPPER_FLARE_DANCER, []{return (HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(HOOKSHOT)) && (IsAdult || KokiriSword || Slingshot || Boomerang);});}}),
Entrance(FIRE_TEMPLE_WEST_CLIMB, {[]{return Here(FIRE_TEMPLE_UPPER_FLARE_DANCER, []{return (HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(HOOKSHOT)) && (IsAdult || KokiriSword || Slingshot || Boomerang);});}}),
Entrance(RR_FIRE_TEMPLE_LATE_FIRE_MAZE, {[]{return Here(RR_FIRE_TEMPLE_UPPER_FLARE_DANCER, []{return (HasExplosives || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_HOOKSHOT)) && (IsAdult || KokiriSword || Slingshot || Boomerang);});}}),
Entrance(RR_FIRE_TEMPLE_WEST_CLIMB, {[]{return Here(RR_FIRE_TEMPLE_UPPER_FLARE_DANCER, []{return (HasExplosives || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_HOOKSHOT)) && (IsAdult || KokiriSword || Slingshot || Boomerang);});}}),
});
areaTable[FIRE_TEMPLE_WEST_CLIMB] = Area("Fire Temple West Climb", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_WEST_CLIMB] = Area("Fire Temple West Climb", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_UPPER_FLARE_DANCER, {[]{return true;}}),
Entrance(FIRE_TEMPLE_WEST_PEAK, {[]{return CanUseProjectile;}}),
Entrance(RR_FIRE_TEMPLE_UPPER_FLARE_DANCER, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_WEST_PEAK, {[]{return CanUseProjectile;}}),
});
areaTable[FIRE_TEMPLE_WEST_PEAK] = Area("Fire Temple West Peak", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_WEST_PEAK] = Area("Fire Temple West Peak", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_MEGATON_HAMMER_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_WEST_CENTRAL_UPPER, {[]{return CanTakeDamage;}}),
Entrance(FIRE_TEMPLE_WEST_CLIMB, {[]{return true;}}),
Entrance(FIRE_TEMPLE_HAMMER_RETURN_PATH, {[]{return CanUse(MEGATON_HAMMER);}}),
Entrance(RR_FIRE_TEMPLE_WEST_CENTRAL_UPPER, {[]{return CanTakeDamage;}}),
Entrance(RR_FIRE_TEMPLE_WEST_CLIMB, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_HAMMER_RETURN_PATH, {[]{return CanUse(RG_MEGATON_HAMMER);}}),
});
areaTable[FIRE_TEMPLE_HAMMER_RETURN_PATH] = Area("Fire Temple Hammer Return Path", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_HAMMER_RETURN_PATH] = Area("Fire Temple Hammer Return Path", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_ABOVE_FIRE_MAZE, {[]{return CanUse(MEGATON_HAMMER);}}),
Entrance(RR_FIRE_TEMPLE_ABOVE_FIRE_MAZE, {[]{return CanUse(RG_MEGATON_HAMMER);}}),
});
areaTable[FIRE_TEMPLE_ABOVE_FIRE_MAZE] = Area("Fire Temple Above Fire Maze", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FIRE_TEMPLE_ABOVE_FIRE_MAZE] = Area("Fire Temple Above Fire Maze", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FIRE_TEMPLE_HAMMER_RETURN_PATH, {[]{return true;}}),
Entrance(FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return CanUse(MEGATON_HAMMER);}}),
Entrance(RR_FIRE_TEMPLE_HAMMER_RETURN_PATH, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return CanUse(RG_MEGATON_HAMMER);}}),
});
}
@@ -312,110 +312,110 @@ void AreaTable_Init_FireTemple() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::FireTemple.IsMQ()) {
areaTable[FIRE_TEMPLE_MQ_LOWER] = Area("Fire Temple MQ Lower", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_MQ_LOWER] = Area("Fire Temple MQ Lower", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, {[]{return IsAdult || KokiriSword || Sticks || Slingshot || Bombs || CanUse(DINS_FIRE);}}),
LocationAccess(FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, {[]{return IsAdult && (LogicFewerTunicRequirements || CanUse(GORON_TUNIC)) && (((CanUse(HOVER_BOOTS) || (LogicFireMQNearBoss && CanUse(BOW))) && HasFireSource) || (CanUse(HOOKSHOT) && CanUse(FIRE_ARROWS) || (CanUse(DINS_FIRE) && ((DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_QUADRUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OCTUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_SEXDECUPLE)) || CanUse(GORON_TUNIC) || CanUse(BOW) || CanUse(LONGSHOT)))));}}),
//Trick: IsAdult && (LogicFewerTunicRequirements || CanUse(GORON_TUNIC)) && (((CanUse(HOVER_BOOTS) || (LogicFireMQNearBoss && CanUse(BOW))) && HasFireSource) || (CanUse(HOOKSHOT) && CanUse(FIRE_ARROWS) || (CanUse(DINS_FIRE) && ((DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_QUADRUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OCTUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_SEXDECUPLE)) || CanUse(GORON_TUNIC) || CanUse(BOW) || CanUse(LONGSHOT)))))
LocationAccess(RC_FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST, {[]{return IsAdult || KokiriSword || Sticks || Slingshot || Bombs || CanUse(RG_DINS_FIRE);}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST, {[]{return IsAdult && (LogicFewerTunicRequirements || CanUse(RG_GORON_TUNIC)) && (((CanUse(RG_HOVER_BOOTS) || (LogicFireMQNearBoss && CanUse(RG_FAIRY_BOW))) && HasFireSource) || (CanUse(RG_HOOKSHOT) && CanUse(RG_FIRE_ARROWS) || (CanUse(RG_DINS_FIRE) && ((DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_QUADRUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OCTUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_SEXDECUPLE)) || CanUse(RG_GORON_TUNIC) || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)))));}}),
//Trick: IsAdult && (LogicFewerTunicRequirements || CanUse(RG_GORON_TUNIC)) && (((CanUse(RG_HOVER_BOOTS) || (LogicFireMQNearBoss && CanUse(RG_FAIRY_BOW))) && HasFireSource) || (CanUse(RG_HOOKSHOT) && CanUse(RG_FIRE_ARROWS) || (CanUse(RG_DINS_FIRE) && ((DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_QUADRUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OCTUPLE) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_SEXDECUPLE)) || CanUse(RG_GORON_TUNIC) || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)))))
}, {
//Exits
Entrance(FIRE_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return IsAdult && CanUse(GORON_TUNIC) && CanUse(MEGATON_HAMMER) && BossKeyFireTemple && ((HasFireSource && (LogicFireBossDoorJump || HoverBoots)) || HasAccessTo(FIRE_TEMPLE_MQ_UPPER));}}),
Entrance(FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR, {[]{return SmallKeys(FIRE_TEMPLE, 5) && (IsAdult || KokiriSword);}}),
Entrance(FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, {[]{return IsAdult && FireTimer >= 24 && CanUse(MEGATON_HAMMER);}}),
Entrance(RR_FIRE_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && CanUse(RG_MEGATON_HAMMER) && BossKeyFireTemple && ((HasFireSource && (LogicFireBossDoorJump || HoverBoots)) || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER));}}),
Entrance(RR_FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR, {[]{return SmallKeys(RR_FIRE_TEMPLE, 5) && (IsAdult || KokiriSword);}}),
Entrance(RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM, {[]{return IsAdult && FireTimer >= 24 && CanUse(RG_MEGATON_HAMMER);}}),
});
areaTable[FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR] = Area("Fire Temple MQ Lower Locked Door", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR] = Area("Fire Temple MQ Lower Locked Door", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, {[]{return IsAdult && (HasExplosives || Hammer || Hookshot);}}),
LocationAccess(FIRE_TEMPLE_MQ_MAP_CHEST, {[]{return IsAdult && CanUse(MEGATON_HAMMER);}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST, {[]{return IsAdult && (HasExplosives || Hammer || Hookshot);}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_MAP_CHEST, {[]{return IsAdult && CanUse(RG_MEGATON_HAMMER);}}),
}, {});
areaTable[FIRE_TEMPLE_MQ_BIG_LAVA_ROOM] = Area("Fire Temple MQ Big Lava Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM] = Area("Fire Temple MQ Big Lava Room", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return FairyPot || (HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && (CanUse(HOOKSHOT) || LogicFireSongOfTime));}}),
//Trick: HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && (CanUse(HOOKSHOT) || LogicFireSongOfTime)
EventAccess(&FairyPot, {[]{return FairyPot || (HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireSongOfTime));}}),
//Trick: HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireSongOfTime)
}, {
//Locations
LocationAccess(FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && CanUse(HOOKSHOT);}}),
//Trick: HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && CanUse(HOOKSHOT)
LocationAccess(FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return HasFireSource && HasExplosives && IsAdult && (CanUse(HOOKSHOT) || LogicFireMQBlockedChest);}}),
//Trick: HasFireSource && HasExplosives && IsAdult && (CanUse(HOOKSHOT) || LogicFireMQBlockedChest)
LocationAccess(FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && CanUse(RG_HOOKSHOT);}}),
//Trick: HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && CanUse(RG_HOOKSHOT)
LocationAccess(RC_FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return HasFireSource && HasExplosives && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireMQBlockedChest);}}),
//Trick: HasFireSource && HasExplosives && IsAdult && (CanUse(RG_HOOKSHOT) || LogicFireMQBlockedChest)
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR, {[]{return true;}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return IsAdult && CanUse(GORON_TUNIC) && SmallKeys(FIRE_TEMPLE, 2) && (HasFireSource || (LogicFireMQClimb && HoverBoots));}}),
//Trick: IsAdult && CanUse(GORON_TUNIC) && SmallKeys(FIRE_TEMPLE, 2) && (HasFireSource || (LogicFireMQClimb && HoverBoots))
Entrance(RR_FIRE_TEMPLE_MQ_LOWER_MAZE, {[]{return IsAdult && CanUse(RG_GORON_TUNIC) && SmallKeys(RR_FIRE_TEMPLE, 2) && (HasFireSource || (LogicFireMQClimb && HoverBoots));}}),
//Trick: IsAdult && CanUse(RG_GORON_TUNIC) && SmallKeys(RR_FIRE_TEMPLE, 2) && (HasFireSource || (LogicFireMQClimb && HoverBoots))
});
areaTable[FIRE_TEMPLE_MQ_LOWER_MAZE] = Area("Fire Temple MQ Lower Maze", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_MQ_LOWER_MAZE] = Area("Fire Temple MQ Lower Maze", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, {[]{return true;}}),
LocationAccess(FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, {[]{return HasExplosives && (LogicFireMQMazeSideRoom || HasAccessTo(FIRE_TEMPLE_MQ_UPPER_MAZE));}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, {[]{return HasExplosives && (LogicFireMQMazeSideRoom || HasAccessTo(RR_FIRE_TEMPLE_MQ_UPPER_MAZE));}}),
//Trick: HasExplosives && (LogicFireMQMazeSideRoom || FIRE_TEMPLE_MQ_UPPER_MAZE.Adult())
}, {
//Exits
Entrance(FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return (IsAdult && ((HasExplosives && CanUse(HOOKSHOT)) || (LogicFireMQMazeHovers && CanUse(HOVER_BOOTS)))) || LogicFireMQMazeJump;}}),
//Trick: (IsAdult && ((HasExplosives && CanUse(HOOKSHOT)) || (LogicFireMQMazeHovers && CanUse(HOVER_BOOTS)))) || LogicFireMQMazeJump
Entrance(RR_FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return (IsAdult && ((HasExplosives && CanUse(RG_HOOKSHOT)) || (LogicFireMQMazeHovers && CanUse(RG_HOVER_BOOTS)))) || LogicFireMQMazeJump;}}),
//Trick: (IsAdult && ((HasExplosives && CanUse(RG_HOOKSHOT)) || (LogicFireMQMazeHovers && CanUse(RG_HOVER_BOOTS)))) || LogicFireMQMazeJump
});
areaTable[FIRE_TEMPLE_MQ_UPPER_MAZE] = Area("Fire Temple MQ Upper Maze", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FIRE_TEMPLE_MQ_UPPER_MAZE] = Area("Fire Temple MQ Upper Maze", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
//EventAccess(&WallFairy, {[]{return WallFairy || (IsAdult && (((CanPlay(SongOfTime) && CanUse(HOOKSHOT) && HasExplosives) || CanUse(LONGSHOT))));}}),
EventAccess(&FairyPot, {[]{return SmallKeys(FIRE_TEMPLE, 3);}}),
//EventAccess(&WallFairy, {[]{return WallFairy || (IsAdult && (((CanPlay(SongOfTime) && CanUse(RG_HOOKSHOT) && HasExplosives) || CanUse(RG_LONGSHOT))));}}),
EventAccess(&FairyPot, {[]{return SmallKeys(RR_FIRE_TEMPLE, 3);}}),
}, {
//Locations
LocationAccess(FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, {[]{return true;}}),
LocationAccess(FIRE_TEMPLE_MQ_COMPASS_CHEST, {[]{return HasExplosives;}}),
LocationAccess(FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, {[]{return IsAdult && ((CanPlay(SongOfTime) && CanUse(HOOKSHOT) && HasExplosives) || CanUse(LONGSHOT));}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST, {[]{return true;}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_COMPASS_CHEST, {[]{return HasExplosives;}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE, {[]{return IsAdult && ((CanPlay(SongOfTime) && CanUse(RG_HOOKSHOT) && HasExplosives) || CanUse(RG_LONGSHOT));}}),
}, {
//Exits
Entrance(FIRE_TEMPLE_MQ_UPPER, {[]{return SmallKeys(FIRE_TEMPLE, 3) && IsAdult && ((CanUse(BOW) && CanUse(HOOKSHOT)) || CanUse(FIRE_ARROWS));}}),
Entrance(RR_FIRE_TEMPLE_MQ_UPPER, {[]{return SmallKeys(RR_FIRE_TEMPLE, 3) && IsAdult && ((CanUse(RG_FAIRY_BOW) && CanUse(RG_HOOKSHOT)) || CanUse(RG_FIRE_ARROWS));}}),
});
areaTable[FIRE_TEMPLE_MQ_UPPER] = Area("Fire Temple MQ Upper", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FIRE_TEMPLE_MQ_UPPER] = Area("Fire Temple MQ Upper", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FIRE_TEMPLE_MQ_FREESTANDING_KEY, {[]{return (IsAdult && CanUse(HOOKSHOT)) || LogicFireMQFlameMaze;}}),
//Trick: (IsAdult && CanUse(HOOKSHOT)) || LogicFireMQFlameMaze
LocationAccess(FIRE_TEMPLE_MQ_CHEST_ON_FIRE, {[]{return ((IsAdult && CanUse(HOOKSHOT)) || LogicFireMQFlameMaze) && SmallKeys(FIRE_TEMPLE, 4);}}),
//Trick: ((IsAdult && CanUse(HOOKSHOT)) || LogicFireMQFlameMaze) && SmallKeys(FIRE_TEMPLE, 4)
LocationAccess(FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, {[]{return CanPlay(SongOfTime) || HoverBoots || LogicFireMQFlameMaze;}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, {[]{return (IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze;}}),
//Trick: (IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze
LocationAccess(RC_FIRE_TEMPLE_MQ_CHEST_ON_FIRE, {[]{return ((IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze) && SmallKeys(RR_FIRE_TEMPLE, 4);}}),
//Trick: ((IsAdult && CanUse(RG_HOOKSHOT)) || LogicFireMQFlameMaze) && SmallKeys(RR_FIRE_TEMPLE, 4)
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM, {[]{return CanPlay(SongOfTime) || HoverBoots || LogicFireMQFlameMaze;}}),
//Trick: CanPlay(SongOfTime) || HoverBoots || LogicFireMQFlameMaze
LocationAccess(FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, {[]{return HasExplosives;}}),
LocationAccess(FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, {[]{return (IsAdult && CanUse(HOOKSHOT) && SmallKeys(FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(LONGSHOT));}}),
//Trick: (IsAdult && CanUse(HOOKSHOT) && SmallKeys(FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(LONGSHOT))
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER, {[]{return HasExplosives;}}),
LocationAccess(RC_FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE, {[]{return (IsAdult && CanUse(RG_HOOKSHOT) && SmallKeys(RR_FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(RG_LONGSHOT));}}),
//Trick: (IsAdult && CanUse(RG_HOOKSHOT) && SmallKeys(RR_FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(RG_LONGSHOT))
}, {});
}
/*---------------------------
| BOSS ROOM |
---------------------------*/
areaTable[FIRE_TEMPLE_BOSS_ENTRYWAY] =
Area("Fire Temple Boss Entryway", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_FIRE_TEMPLE_BOSS_ENTRYWAY] =
Area("Fire Temple Boss Entryway", "Fire Temple", RHT_FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(FIRE_TEMPLE_NEAR_BOSS_ROOM, { [] { return Dungeon::FireTemple.IsVanilla() && false; } }),
Entrance(FIRE_TEMPLE_MQ_LOWER, { [] { return Dungeon::FireTemple.IsMQ() && false; } }),
Entrance(FIRE_TEMPLE_BOSS_ROOM, { [] { return true; } }),
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, { [] { return Dungeon::FireTemple.IsVanilla() && false; } }),
Entrance(RR_FIRE_TEMPLE_MQ_LOWER, { [] { return Dungeon::FireTemple.IsMQ() && false; } }),
Entrance(RR_FIRE_TEMPLE_BOSS_ROOM, { [] { return true; } }),
});
areaTable[FIRE_TEMPLE_BOSS_ROOM] =
Area("Fire Temple Boss Room", "Fire Temple", NONE, NO_DAY_NIGHT_CYCLE,
areaTable[RR_FIRE_TEMPLE_BOSS_ROOM] =
Area("Fire Temple Boss Room", "Fire Temple", RHT_NONE, NO_DAY_NIGHT_CYCLE,
{
// Events
EventAccess(&FireTempleClear,
{ [] { return FireTempleClear || (HasBossSoul(VOLVAGIA_BOSS_SOUL) && (FireTimer >= 64 && CanUse(MEGATON_HAMMER))); }}),
{ [] { return FireTempleClear || (HasBossSoul(RG_VOLVAGIA_SOUL) && (FireTimer >= 64 && CanUse(RG_MEGATON_HAMMER))); }}),
},
{
// Locations
LocationAccess(FIRE_TEMPLE_VOLVAGIA_HEART, { [] { return FireTempleClear; } }),
LocationAccess(VOLVAGIA, { [] { return FireTempleClear; } }),
LocationAccess(RC_FIRE_TEMPLE_VOLVAGIA_HEART, { [] { return FireTempleClear; } }),
LocationAccess(RC_VOLVAGIA, { [] { return FireTempleClear; } }),
},
{
// Exits
Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
});
}

View File

@@ -10,269 +10,269 @@ void AreaTable_Init_ForestTemple() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[FOREST_TEMPLE_ENTRYWAY] = Area("Forest Temple Entryway", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FOREST_TEMPLE_ENTRYWAY] = Area("Forest Temple Entryway", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FOREST_TEMPLE_FIRST_ROOM, {[]{return Dungeon::ForestTemple.IsVanilla();}}),
Entrance(FOREST_TEMPLE_MQ_LOBBY, {[]{return Dungeon::ForestTemple.IsMQ();}}),
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_FIRST_ROOM, {[]{return Dungeon::ForestTemple.IsVanilla();}}),
Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, {[]{return Dungeon::ForestTemple.IsMQ();}}),
Entrance(RR_SACRED_FOREST_MEADOW, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::ForestTemple.IsVanilla()) {
areaTable[FOREST_TEMPLE_FIRST_ROOM] = Area("Forest Temple First Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_FIRST_ROOM] = Area("Forest Temple First Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_FIRST_ROOM_CHEST, {[]{return true;}}),
LocationAccess(FOREST_TEMPLE_GS_FIRST_ROOM, {[]{return (IsAdult && Bombs) || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(BOOMERANG) || CanUse(SLINGSHOT) || HasBombchus || CanUse(DINS_FIRE) || (LogicForestFirstGS && (CanJumpslash || (IsChild && Bombs)));}}),
LocationAccess(RC_FOREST_TEMPLE_FIRST_ROOM_CHEST, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_GS_FIRST_ROOM, {[]{return (IsAdult && Bombs) || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG) || CanUse(RG_FAIRY_SLINGSHOT) || HasBombchus || CanUse(RG_DINS_FIRE) || (LogicForestFirstGS && (CanJumpslash || (IsChild && Bombs)));}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(FOREST_TEMPLE_SOUTH_CORRIDOR, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_SOUTH_CORRIDOR, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_SOUTH_CORRIDOR] = Area("Forest Temple South Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FOREST_TEMPLE_SOUTH_CORRIDOR] = Area("Forest Temple South Corridor", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FOREST_TEMPLE_FIRST_ROOM, {[]{return true;}}),
Entrance(FOREST_TEMPLE_LOBBY, {[]{return IsAdult || CanChildAttack || Nuts;}}),
Entrance(RR_FOREST_TEMPLE_FIRST_ROOM, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return IsAdult || CanChildAttack || Nuts;}}),
});
areaTable[FOREST_TEMPLE_LOBBY] = Area("Forest Temple Lobby", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_LOBBY] = Area("Forest Temple Lobby", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ForestTempleMeg, {[]{return ForestTempleMeg || (ForestTempleJoelle && ForestTempleBeth && ForestTempleAmy && CanUse(BOW));}}),
EventAccess(&ForestTempleMeg, {[]{return ForestTempleMeg || (ForestTempleJoelle && ForestTempleBeth && ForestTempleAmy && CanUse(RG_FAIRY_BOW));}}),
}, {
//Locations
LocationAccess(FOREST_TEMPLE_GS_LOBBY, {[]{return HookshotOrBoomerang;}}),
LocationAccess(RC_FOREST_TEMPLE_GS_LOBBY, {[]{return HookshotOrBoomerang;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_SOUTH_CORRIDOR, {[]{return true;}}),
Entrance(FOREST_TEMPLE_NORTH_CORRIDOR, {[]{return true;}}),
Entrance(FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return CanPlay(SongOfTime) || IsChild;}}),
Entrance(FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return CanUse(BOW) || CanUse(SLINGSHOT);}}),
Entrance(FOREST_TEMPLE_WEST_CORRIDOR, {[]{return SmallKeys(FOREST_TEMPLE, 1, 5);}}),
Entrance(FOREST_TEMPLE_EAST_CORRIDOR, {[]{return false;}}),
Entrance(FOREST_TEMPLE_BOSS_REGION, {[]{return ForestTempleMeg;}}),
Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return false;}}),
Entrance(RR_FOREST_TEMPLE_SOUTH_CORRIDOR, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NORTH_CORRIDOR, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return CanPlay(SongOfTime) || IsChild;}}),
Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT);}}),
Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, {[]{return SmallKeys(RR_FOREST_TEMPLE, 1, 5);}}),
Entrance(RR_FOREST_TEMPLE_EAST_CORRIDOR, {[]{return false;}}),
Entrance(RR_FOREST_TEMPLE_BOSS_REGION, {[]{return ForestTempleMeg;}}),
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return false;}}),
});
areaTable[FOREST_TEMPLE_NORTH_CORRIDOR] = Area("Forest Temple North Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FOREST_TEMPLE_NORTH_CORRIDOR] = Area("Forest Temple North Corridor", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FOREST_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(FOREST_TEMPLE_LOWER_STALFOS, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_LOWER_STALFOS, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_LOWER_STALFOS] = Area("Forest Temple Lower Stalfos", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_LOWER_STALFOS] = Area("Forest Temple Lower Stalfos", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(FOREST_TEMPLE_FIRST_STALFOS_CHEST, {[]{return IsAdult || KokiriSword;}}),
LocationAccess(RC_FOREST_TEMPLE_FIRST_STALFOS_CHEST, {[]{return IsAdult || KokiriSword;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_NORTH_CORRIDOR, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NORTH_CORRIDOR, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_NW_OUTDOORS_LOWER] = Area("Forest Temple NW Outdoors Lower", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER] = Area("Forest Temple NW Outdoors Lower", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
}, {
//Locations
LocationAccess(FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, {[]{return CanUse(LONGSHOT) || Here(FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return HookshotOrBoomerang;});}}),
LocationAccess(RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, {[]{return CanUse(RG_LONGSHOT) || Here(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return HookshotOrBoomerang;});}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_LOBBY, {[]{return CanPlay(SongOfTime);}}),
Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return false;}}),
Entrance(FOREST_TEMPLE_MAP_ROOM, {[]{return true;}}),
Entrance(FOREST_TEMPLE_SEWER, {[]{return GoldScale || CanUse(IRON_BOOTS) || HasAccessTo(FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}),
Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return false;}}),
Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return CanPlay(SongOfTime);}}),
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return false;}}),
Entrance(RR_FOREST_TEMPLE_MAP_ROOM, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_SEWER, {[]{return GoldScale || CanUse(RG_IRON_BOOTS) || HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}),
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return false;}}),
});
areaTable[FOREST_TEMPLE_NW_OUTDOORS_UPPER] = Area("Forest Temple NW Outdoors Upper", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER] = Area("Forest Temple NW Outdoors Upper", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
}, {}, {
//Exits
Entrance(FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return true;}}),
Entrance(FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, {[]{return true;}}),
Entrance(FOREST_TEMPLE_FLOORMASTER_ROOM, {[]{return true;}}),
Entrance(FOREST_TEMPLE_BLOCK_PUSH_ROOM, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_FLOORMASTER_ROOM, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_NE_OUTDOORS_LOWER] = Area("Forest Temple NE Outdoors Lower", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER] = Area("Forest Temple NE Outdoors Lower", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
}, {
//Locations
LocationAccess(FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, {[]{return CanUse(HOOKSHOT) || HasAccessTo(FOREST_TEMPLE_FALLING_ROOM) || (HasAccessTo(FOREST_TEMPLE_NE_OUTDOORS_UPPER) && IsAdult && LogicForestOutdoorsLedge && HoverBoots);}}),
LocationAccess(FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, {[]{return CanUse(HOOKSHOT) || (LogicForestOutdoorEastGS && CanUse(BOOMERANG)) || Here(FOREST_TEMPLE_FALLING_ROOM, []{return CanUse(BOW) || CanUse(SLINGSHOT) || CanUse(DINS_FIRE) || HasExplosives;});}}),
LocationAccess(RC_FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, {[]{return CanUse(RG_HOOKSHOT) || HasAccessTo(RR_FOREST_TEMPLE_FALLING_ROOM) || (HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER) && IsAdult && LogicForestOutdoorsLedge && HoverBoots);}}),
LocationAccess(RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD, {[]{return CanUse(RG_HOOKSHOT) || (LogicForestOutdoorEastGS && CanUse(RG_BOOMERANG)) || Here(RR_FOREST_TEMPLE_FALLING_ROOM, []{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_DINS_FIRE) || HasExplosives;});}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(FOREST_TEMPLE_NE_OUTDOORS_UPPER, {[]{return CanUse(LONGSHOT) || (LogicForestVines && CanUse(HOOKSHOT));}}),
Entrance(FOREST_TEMPLE_SEWER, {[]{return GoldScale || CanUse(IRON_BOOTS) || HasAccessTo(FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}),
Entrance(FOREST_TEMPLE_FALLING_ROOM, {[]{return false;}}),
Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER, {[]{return CanUse(RG_LONGSHOT) || (LogicForestVines && CanUse(RG_HOOKSHOT));}}),
Entrance(RR_FOREST_TEMPLE_SEWER, {[]{return GoldScale || CanUse(RG_IRON_BOOTS) || HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}),
Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, {[]{return false;}}),
});
areaTable[FOREST_TEMPLE_NE_OUTDOORS_UPPER] = Area("Forest Temple NE Outdoors Upper", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER] = Area("Forest Temple NE Outdoors Upper", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
}, {}, {
//Exits
Entrance(FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return true;}}),
Entrance(FOREST_TEMPLE_MAP_ROOM, {[]{return true;}}),
Entrance(FOREST_TEMPLE_FALLING_ROOM, {[]{return LogicForestDoorFrame && CanUse(HOVER_BOOTS) && CanUse(SCARECROW);}}),
Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_MAP_ROOM, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, {[]{return LogicForestDoorFrame && CanUse(RG_HOVER_BOOTS) && CanUse(RG_SCARECROW);}}),
});
areaTable[FOREST_TEMPLE_MAP_ROOM] = Area("Forest Temple Map Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_MAP_ROOM] = Area("Forest Temple Map Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_MAP_CHEST, {[]{return Here(FOREST_TEMPLE_MAP_ROOM, []{return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || ((IsAdult || Sticks || KokiriSword || Slingshot) && (Nuts || HookshotOrBoomerang || CanShield));});}}),
LocationAccess(RC_FOREST_TEMPLE_MAP_CHEST, {[]{return Here(RR_FOREST_TEMPLE_MAP_ROOM, []{return HasExplosives || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_FAIRY_BOW) || ((IsAdult || Sticks || KokiriSword || Slingshot) && (Nuts || HookshotOrBoomerang || CanShield));});}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return Here(FOREST_TEMPLE_MAP_ROOM, []{return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || ((IsAdult || Sticks || KokiriSword || Slingshot) && (Nuts || HookshotOrBoomerang || CanShield));});}}),
Entrance(FOREST_TEMPLE_NE_OUTDOORS_UPPER, {[]{return Here(FOREST_TEMPLE_MAP_ROOM, []{return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || ((IsAdult || Sticks || KokiriSword || Slingshot) && (Nuts || HookshotOrBoomerang || CanShield));});}}),
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return Here(RR_FOREST_TEMPLE_MAP_ROOM, []{return HasExplosives || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_FAIRY_BOW) || ((IsAdult || Sticks || KokiriSword || Slingshot) && (Nuts || HookshotOrBoomerang || CanShield));});}}),
Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER, {[]{return Here(RR_FOREST_TEMPLE_MAP_ROOM, []{return HasExplosives || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_FAIRY_BOW) || ((IsAdult || Sticks || KokiriSword || Slingshot) && (Nuts || HookshotOrBoomerang || CanShield));});}}),
});
areaTable[FOREST_TEMPLE_SEWER] = Area("Forest Temple Sewer", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_SEWER] = Area("Forest Temple Sewer", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_WELL_CHEST, {[]{return HasAccessTo(FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}),
LocationAccess(RC_FOREST_TEMPLE_WELL_CHEST, {[]{return HasAccessTo(RR_FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return true;}}),
Entrance(FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST] = Area("Forest Temple Below Boss Key Chest", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST] = Area("Forest Temple Below Boss Key Chest", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return Here(FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, []{return HasExplosives || CanUse(MEGATON_HAMMER) || CanUse(BOW) || ((IsAdult || Sticks || KokiriSword || Slingshot) && (Nuts || HookshotOrBoomerang || CanShield));});}}),
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return Here(RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, []{return HasExplosives || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_FAIRY_BOW) || ((IsAdult || Sticks || KokiriSword || Slingshot) && (Nuts || HookshotOrBoomerang || CanShield));});}}),
});
areaTable[FOREST_TEMPLE_FLOORMASTER_ROOM] = Area("Forest Temple Floormaster Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_FLOORMASTER_ROOM] = Area("Forest Temple Floormaster Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_FLOORMASTER_CHEST, {[]{return IsAdult || CanChildDamage;}}),
LocationAccess(RC_FOREST_TEMPLE_FLOORMASTER_CHEST, {[]{return IsAdult || CanChildDamage;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_WEST_CORRIDOR] = Area("Forest Temple West Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FOREST_TEMPLE_WEST_CORRIDOR] = Area("Forest Temple West Corridor", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FOREST_TEMPLE_LOBBY, {[]{return SmallKeys(FOREST_TEMPLE, 1, 5);}}),
Entrance(FOREST_TEMPLE_BLOCK_PUSH_ROOM, {[]{return IsAdult || CanChildAttack || Nuts;}}),
Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return SmallKeys(RR_FOREST_TEMPLE, 1, 5);}}),
Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM, {[]{return IsAdult || CanChildAttack || Nuts;}}),
});
areaTable[FOREST_TEMPLE_BLOCK_PUSH_ROOM] = Area("Forest Temple Block Push Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM] = Area("Forest Temple Block Push Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_EYE_SWITCH_CHEST, {[]{return GoronBracelet && (CanUse(BOW) || CanUse(SLINGSHOT));}}),
LocationAccess(RC_FOREST_TEMPLE_EYE_SWITCH_CHEST, {[]{return GoronBracelet && (CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT));}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_WEST_CORRIDOR, {[]{return true;}}),
Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return CanUse(HOVER_BOOTS) || (LogicForestOutsideBackdoor && CanJumpslash && GoronBracelet);}}),
Entrance(FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return IsAdult && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);}}),
Entrance(FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return CanUse(BOW) && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);}}),
Entrance(RR_FOREST_TEMPLE_WEST_CORRIDOR, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return CanUse(RG_HOVER_BOOTS) || (LogicForestOutsideBackdoor && CanJumpslash && GoronBracelet);}}),
Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return IsAdult && GoronBracelet && SmallKeys(RR_FOREST_TEMPLE, 2);}}),
Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return CanUse(RG_FAIRY_BOW) && GoronBracelet && SmallKeys(RR_FOREST_TEMPLE, 2);}}),
});
areaTable[FOREST_TEMPLE_NW_CORRIDOR_TWISTED] = Area("Forest Temple NW Corridor Twisted", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED] = Area("Forest Temple NW Corridor Twisted", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FOREST_TEMPLE_BLOCK_PUSH_ROOM, {[]{return SmallKeys(FOREST_TEMPLE, 2);}}),
Entrance(FOREST_TEMPLE_RED_POE_ROOM, {[]{return SmallKeys(FOREST_TEMPLE, 3);}}),
Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM, {[]{return SmallKeys(RR_FOREST_TEMPLE, 2);}}),
Entrance(RR_FOREST_TEMPLE_RED_POE_ROOM, {[]{return SmallKeys(RR_FOREST_TEMPLE, 3);}}),
});
areaTable[FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED] = Area("Forest Temple NW Corridor Straightened", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED] = Area("Forest Temple NW Corridor Straightened", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, {[]{return true;}}),
Entrance(FOREST_TEMPLE_BLOCK_PUSH_ROOM, {[]{return SmallKeys(FOREST_TEMPLE, 2);}}),
Entrance(RR_FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_BLOCK_PUSH_ROOM, {[]{return SmallKeys(RR_FOREST_TEMPLE, 2);}}),
});
areaTable[FOREST_TEMPLE_RED_POE_ROOM] = Area("Forest Temple Red Poe Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_RED_POE_ROOM] = Area("Forest Temple Red Poe Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ForestTempleJoelle, {[]{return ForestTempleJoelle || CanUse(BOW);}}),
EventAccess(&ForestTempleJoelle, {[]{return ForestTempleJoelle || CanUse(RG_FAIRY_BOW);}}),
}, {
//Locations
LocationAccess(FOREST_TEMPLE_RED_POE_CHEST, {[]{return ForestTempleJoelle;}}),
LocationAccess(RC_FOREST_TEMPLE_RED_POE_CHEST, {[]{return ForestTempleJoelle;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return SmallKeys(FOREST_TEMPLE, 3);}}),
Entrance(FOREST_TEMPLE_UPPER_STALFOS, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return SmallKeys(RR_FOREST_TEMPLE, 3);}}),
Entrance(RR_FOREST_TEMPLE_UPPER_STALFOS, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_UPPER_STALFOS] = Area("Forest Temple Upper Stalfos", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_UPPER_STALFOS] = Area("Forest Temple Upper Stalfos", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_BOW_CHEST, {[]{return IsAdult || KokiriSword;}}),
LocationAccess(RC_FOREST_TEMPLE_BOW_CHEST, {[]{return IsAdult || KokiriSword;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_RED_POE_ROOM, {[]{return IsAdult || KokiriSword;}}),
Entrance(FOREST_TEMPLE_BLUE_POE_ROOM, {[]{return IsAdult || KokiriSword;}}),
Entrance(RR_FOREST_TEMPLE_RED_POE_ROOM, {[]{return IsAdult || KokiriSword;}}),
Entrance(RR_FOREST_TEMPLE_BLUE_POE_ROOM, {[]{return IsAdult || KokiriSword;}}),
});
areaTable[FOREST_TEMPLE_BLUE_POE_ROOM] = Area("Forest Temple Blue Poe Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_BLUE_POE_ROOM] = Area("Forest Temple Blue Poe Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ForestTempleBeth, {[]{return ForestTempleBeth || CanUse(BOW);}}),
EventAccess(&ForestTempleBeth, {[]{return ForestTempleBeth || CanUse(RG_FAIRY_BOW);}}),
}, {
//Locations
LocationAccess(FOREST_TEMPLE_BLUE_POE_CHEST, {[]{return ForestTempleBeth;}}),
LocationAccess(RC_FOREST_TEMPLE_BLUE_POE_CHEST, {[]{return ForestTempleBeth;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_UPPER_STALFOS, {[]{return true;}}),
Entrance(FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED, {[]{return SmallKeys(FOREST_TEMPLE, 4);}}),
Entrance(RR_FOREST_TEMPLE_UPPER_STALFOS, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED, {[]{return SmallKeys(RR_FOREST_TEMPLE, 4);}}),
});
areaTable[FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED] = Area("Forest Temple NE Corridor Straightened", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED] = Area("Forest Temple NE Corridor Straightened", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FOREST_TEMPLE_BLUE_POE_ROOM, {[]{return SmallKeys(FOREST_TEMPLE, 4);}}),
Entrance(FOREST_TEMPLE_FROZEN_EYE_ROOM, {[]{return SmallKeys(FOREST_TEMPLE, 5);}}),
Entrance(RR_FOREST_TEMPLE_BLUE_POE_ROOM, {[]{return SmallKeys(RR_FOREST_TEMPLE, 4);}}),
Entrance(RR_FOREST_TEMPLE_FROZEN_EYE_ROOM, {[]{return SmallKeys(RR_FOREST_TEMPLE, 5);}}),
});
areaTable[FOREST_TEMPLE_NE_CORRIDOR_TWISTED] = Area("Forest Temple NE Corridor Twisted", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FOREST_TEMPLE_NE_CORRIDOR_TWISTED] = Area("Forest Temple NE Corridor Twisted", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FOREST_TEMPLE_FROZEN_EYE_ROOM, {[]{return SmallKeys(FOREST_TEMPLE, 5);}}),
Entrance(FOREST_TEMPLE_FALLING_ROOM, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_FROZEN_EYE_ROOM, {[]{return SmallKeys(RR_FOREST_TEMPLE, 5);}}),
Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_FROZEN_EYE_ROOM] = Area("Forest Temple Frozen Eye Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FOREST_TEMPLE_FROZEN_EYE_ROOM] = Area("Forest Temple Frozen Eye Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED, {[]{return SmallKeys(FOREST_TEMPLE, 5);}}),
Entrance(FOREST_TEMPLE_NE_CORRIDOR_TWISTED, {[]{return SmallKeys(FOREST_TEMPLE, 5) && (CanUse(BOW) || CanUse(DINS_FIRE));}}),
Entrance(RR_FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED, {[]{return SmallKeys(RR_FOREST_TEMPLE, 5);}}),
Entrance(RR_FOREST_TEMPLE_NE_CORRIDOR_TWISTED, {[]{return SmallKeys(RR_FOREST_TEMPLE, 5) && (CanUse(RG_FAIRY_BOW) || CanUse(RG_DINS_FIRE));}}),
});
areaTable[FOREST_TEMPLE_FALLING_ROOM] = Area("Forest Temple Falling Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_FALLING_ROOM] = Area("Forest Temple Falling Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return true;}}),
Entrance(FOREST_TEMPLE_GREEN_POE_ROOM, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_NE_OUTDOORS_LOWER, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_GREEN_POE_ROOM, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_GREEN_POE_ROOM] = Area("Forest Temple Green Poe Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_GREEN_POE_ROOM] = Area("Forest Temple Green Poe Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ForestTempleAmy, {[]{return ForestTempleAmy || CanUse(BOW);}}),
EventAccess(&ForestTempleAmy, {[]{return ForestTempleAmy || CanUse(RG_FAIRY_BOW);}}),
}, {}, {
//Exits
Entrance(FOREST_TEMPLE_FALLING_ROOM, {[]{return true;}}),
Entrance(FOREST_TEMPLE_EAST_CORRIDOR, {[]{return ForestTempleAmy;}}),
Entrance(RR_FOREST_TEMPLE_FALLING_ROOM, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_EAST_CORRIDOR, {[]{return ForestTempleAmy;}}),
});
areaTable[FOREST_TEMPLE_EAST_CORRIDOR] = Area("Forest Temple East Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_FOREST_TEMPLE_EAST_CORRIDOR] = Area("Forest Temple East Corridor", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(FOREST_TEMPLE_LOBBY, {[]{return IsAdult || CanChildAttack || Nuts;}}),
Entrance(FOREST_TEMPLE_GREEN_POE_ROOM, {[]{return IsAdult || CanChildAttack || Nuts;}}),
Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return IsAdult || CanChildAttack || Nuts;}}),
Entrance(RR_FOREST_TEMPLE_GREEN_POE_ROOM, {[]{return IsAdult || CanChildAttack || Nuts;}}),
});
areaTable[FOREST_TEMPLE_BOSS_REGION] = Area("Forest Temple Boss Region", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_BOSS_REGION] = Area("Forest Temple Boss Region", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_BASEMENT_CHEST, {[]{return true;}}),
LocationAccess(FOREST_TEMPLE_GS_BASEMENT, {[]{return HookshotOrBoomerang;}}),
LocationAccess(RC_FOREST_TEMPLE_BASEMENT_CHEST, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_GS_BASEMENT, {[]{return HookshotOrBoomerang;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyForestTemple;}}),
Entrance(RR_FOREST_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyForestTemple;}}),
});
}
@@ -280,158 +280,158 @@ void AreaTable_Init_ForestTemple() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::ForestTemple.IsMQ()) {
areaTable[FOREST_TEMPLE_MQ_LOBBY] = Area("Forest Temple MQ Lobby", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_MQ_LOBBY] = Area("Forest Temple MQ Lobby", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, {[]{return IsAdult || Bombs || CanUse(STICKS) || Nuts || CanUse(BOOMERANG) || CanUse(DINS_FIRE) || KokiriSword || CanUse(SLINGSHOT);}}),
LocationAccess(FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, {[]{return HookshotOrBoomerang;}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST, {[]{return IsAdult || Bombs || CanUse(RG_STICKS) || Nuts || CanUse(RG_BOOMERANG) || CanUse(RG_DINS_FIRE) || KokiriSword || CanUse(RG_FAIRY_SLINGSHOT);}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY, {[]{return HookshotOrBoomerang;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(FOREST_TEMPLE_MQ_CENTRAL_AREA, {[]{return SmallKeys(FOREST_TEMPLE, 1) && (IsAdult || CanChildAttack || Nuts);}}),
Entrance(RR_FOREST_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_MQ_CENTRAL_AREA, {[]{return SmallKeys(RR_FOREST_TEMPLE, 1) && (IsAdult || CanChildAttack || Nuts);}}),
});
areaTable[FOREST_TEMPLE_MQ_CENTRAL_AREA] = Area("Forest Temple MQ Central Area", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_MQ_CENTRAL_AREA] = Area("Forest Temple MQ Central Area", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_WOLFOS_CHEST, {[]{return (CanPlay(SongOfTime) || IsChild) && (IsAdult || CanUse(DINS_FIRE) || CanUse(STICKS) || CanUse(SLINGSHOT) || KokiriSword);}}),
LocationAccess(FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, {[]{return IsAdult || KokiriSword;}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_WOLFOS_CHEST, {[]{return (CanPlay(SongOfTime) || IsChild) && (IsAdult || CanUse(RG_DINS_FIRE) || CanUse(RG_STICKS) || CanUse(RG_FAIRY_SLINGSHOT) || KokiriSword);}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM, {[]{return IsAdult || KokiriSword;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return (IsAdult && CanUse(BOW)) || (IsChild && CanUse(SLINGSHOT));}}),
Entrance(FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return (IsAdult && CanUse(BOW)) || (IsChild && CanUse(SLINGSHOT));}}), //This is as far as child can get
Entrance(FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE, {[]{return IsAdult && (GoronBracelet || (LogicForestMQBlockPuzzle && HasBombchus && IsAdult && CanUse(HOOKSHOT)));}}),
//Trick: IsAdult && (GoronBracelet || (LogicForestMQBlockPuzzle && HasBombchus && IsAdult && CanUse(HOOKSHOT)))
Entrance(FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return (LogicForestMQHallwaySwitchJS && IsAdult && CanUse(HOVER_BOOTS)) || (LogicForestMQHallwaySwitchBoomerang && CanUse(BOOMERANG)) || (LogicForestMQHallwaySwitchHookshot && IsAdult && CanUse(HOOKSHOT));}}),
//Trick (Hookshot trick not added to either n64 or oot3d rando as of yet, to enable in SoH needs uncommenting in randomizer_tricks.cpp): (LogicForestMQHallwaySwitchJS && IsAdult && CanUse(HOVER_BOOTS)) || (LogicForestMQHallwaySwitchHookshot && IsAdult && CanUse(HOOKSHOT))
Entrance(FOREST_TEMPLE_MQ_BOSS_REGION, {[]{return ForestTempleJoAndBeth && ForestTempleAmyAndMeg;}}),
Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return (IsAdult && CanUse(RG_FAIRY_BOW)) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}),
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return (IsAdult && CanUse(RG_FAIRY_BOW)) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}), //This is as far as child can get
Entrance(RR_FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE, {[]{return IsAdult && (GoronBracelet || (LogicForestMQBlockPuzzle && HasBombchus && IsAdult && CanUse(RG_HOOKSHOT)));}}),
//Trick: IsAdult && (GoronBracelet || (LogicForestMQBlockPuzzle && HasBombchus && IsAdult && CanUse(RG_HOOKSHOT)))
Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return (LogicForestMQHallwaySwitchJS && IsAdult && CanUse(RG_HOVER_BOOTS)) || (LogicForestMQHallwaySwitchBoomerang && CanUse(RG_BOOMERANG)) || (LogicForestMQHallwaySwitchHookshot && IsAdult && CanUse(RG_HOOKSHOT));}}),
//Trick (Hookshot trick not added to either n64 or oot3d rando as of yet, to enable in SoH needs uncommenting in randomizer_tricks.cpp): (LogicForestMQHallwaySwitchJS && IsAdult && CanUse(RG_HOVER_BOOTS)) || (LogicForestMQHallwaySwitchHookshot && IsAdult && CanUse(RG_HOOKSHOT))
Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, {[]{return ForestTempleJoAndBeth && ForestTempleAmyAndMeg;}}),
});
areaTable[FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE] = Area("Forest Temple MQ After Block Puzzle", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE] = Area("Forest Temple MQ After Block Puzzle", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(FOREST_TEMPLE, 3);}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(RR_FOREST_TEMPLE, 3);}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_MQ_BOW_REGION, {[]{return SmallKeys(FOREST_TEMPLE, 4);}}),
Entrance(FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return SmallKeys(FOREST_TEMPLE, 3) || (LogicForestMQHallwaySwitchJS && ((IsAdult && CanUse(HOOKSHOT)) || (LogicForestOutsideBackdoor && (IsAdult || (IsChild && CanUse(STICKS))))));}}),
//Trick (Doing the hallway switch jumpslash as child requires sticks and has been added above): SmallKeys(FOREST_TEMPLE, 3) || (LogicForestMQHallwaySwitchJS && ((IsAdult && CanUse(HOOKSHOT)) || LogicForestOutsideBackdoor))
Entrance(FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return SmallKeys(FOREST_TEMPLE, 2);}}),
Entrance(RR_FOREST_TEMPLE_MQ_BOW_REGION, {[]{return SmallKeys(RR_FOREST_TEMPLE, 4);}}),
Entrance(RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return SmallKeys(RR_FOREST_TEMPLE, 3) || (LogicForestMQHallwaySwitchJS && ((IsAdult && CanUse(RG_HOOKSHOT)) || (LogicForestOutsideBackdoor && (IsAdult || (IsChild && CanUse(RG_STICKS))))));}}),
//Trick (Doing the hallway switch jumpslash as child requires sticks and has been added above): SmallKeys(RR_FOREST_TEMPLE, 3) || (LogicForestMQHallwaySwitchJS && ((IsAdult && CanUse(RG_HOOKSHOT)) || LogicForestOutsideBackdoor))
Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return SmallKeys(RR_FOREST_TEMPLE, 2);}}),
});
areaTable[FOREST_TEMPLE_MQ_OUTDOOR_LEDGE] = Area("Forest Temple MQ Outdoor Ledge", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_MQ_OUTDOOR_LEDGE] = Area("Forest Temple MQ Outdoor Ledge", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_REDEAD_CHEST, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_REDEAD_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_MQ_NW_OUTDOORS] = Area("Forest Temple MQ NW Outdoors", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_MQ_NW_OUTDOORS] = Area("Forest Temple MQ NW Outdoors", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, {[]{return true;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return (IsAdult && (CanUse(IRON_BOOTS) || CanUse(LONGSHOT) || (LogicForestMQWellSwim && CanUse(HOOKSHOT)))) || ProgressiveScale >= 2;}}),
//Trick: (IsAdult && (CanUse(IRON_BOOTS) || CanUse(LONGSHOT) || (LogicForestMQWellSwim && CanUse(HOOKSHOT)))) || ProgressiveScale >= 2
Entrance(FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, {[]{return IsAdult && CanUse(FIRE_ARROWS);}}),
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return (IsAdult && (CanUse(RG_IRON_BOOTS) || CanUse(RG_LONGSHOT) || (LogicForestMQWellSwim && CanUse(RG_HOOKSHOT)))) || ProgressiveScale >= 2;}}),
//Trick: (IsAdult && (CanUse(RG_IRON_BOOTS) || CanUse(RG_LONGSHOT) || (LogicForestMQWellSwim && CanUse(RG_HOOKSHOT)))) || ProgressiveScale >= 2
Entrance(RR_FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, {[]{return IsAdult && CanUse(RG_FIRE_ARROWS);}}),
});
areaTable[FOREST_TEMPLE_MQ_NE_OUTDOORS] = Area("Forest Temple MQ NE Outdoors", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_MQ_NE_OUTDOORS] = Area("Forest Temple MQ NE Outdoors", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_WELL_CHEST, {[]{return (IsAdult && CanUse(BOW)) || (IsChild && CanUse(SLINGSHOT));}}),
LocationAccess(FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, {[]{return HookshotOrBoomerang || (IsAdult && CanUse(FIRE_ARROWS) && (CanPlay(SongOfTime) || (CanUse(HOVER_BOOTS) && LogicForestDoorFrame)));}}),
LocationAccess(FOREST_TEMPLE_MQ_GS_WELL, {[]{return (IsAdult && ((CanUse(IRON_BOOTS) && CanUse(HOOKSHOT)) || CanUse(BOW))) || (IsChild && CanUse(SLINGSHOT));}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_WELL_CHEST, {[]{return (IsAdult && CanUse(RG_FAIRY_BOW)) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, {[]{return HookshotOrBoomerang || (IsAdult && CanUse(RG_FIRE_ARROWS) && (CanPlay(SongOfTime) || (CanUse(RG_HOVER_BOOTS) && LogicForestDoorFrame)));}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_GS_WELL, {[]{return (IsAdult && ((CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT)) || CanUse(RG_FAIRY_BOW))) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, {[]{return IsAdult && CanUse(HOOKSHOT) && (CanUse(LONGSHOT) || CanUse(HOVER_BOOTS) || CanPlay(SongOfTime));}}),
Entrance(FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return IsAdult && CanUse(LONGSHOT);}}),
Entrance(RR_FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES, {[]{return IsAdult && CanUse(RG_HOOKSHOT) && (CanUse(RG_LONGSHOT) || CanUse(RG_HOVER_BOOTS) || CanPlay(SongOfTime));}}),
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return IsAdult && CanUse(RG_LONGSHOT);}}),
});
areaTable[FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES] = Area("Forest Temple MQ Outdoors Top Ledges", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES] = Area("Forest Temple MQ Outdoors Top Ledges", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return true;}}),
Entrance(FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return LogicForestOutdoorsLedge && IsAdult && CanUse(HOVER_BOOTS);}}),
//Trick: LogicForestOutdoorsLedge && IsAdult && CanUse(HOVER_BOOTS)
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return LogicForestOutdoorsLedge && IsAdult && CanUse(RG_HOVER_BOOTS);}}),
//Trick: LogicForestOutdoorsLedge && IsAdult && CanUse(RG_HOVER_BOOTS)
});
areaTable[FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE] = Area("Forest Temple MQ NE Outdoors Ledge", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE] = Area("Forest Temple MQ NE Outdoors Ledge", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return true;}}),
Entrance(FOREST_TEMPLE_MQ_FALLING_ROOM, {[]{return CanPlay(SongOfTime);}}),
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, {[]{return CanPlay(SongOfTime);}}),
});
areaTable[FOREST_TEMPLE_MQ_BOW_REGION] = Area("Forest Temple MQ Bow Region", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_MQ_BOW_REGION] = Area("Forest Temple MQ Bow Region", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ForestTempleJoAndBeth, {[]{return ForestTempleJoAndBeth || (IsAdult && CanUse(BOW));}}),
EventAccess(&ForestTempleJoAndBeth, {[]{return ForestTempleJoAndBeth || (IsAdult && CanUse(RG_FAIRY_BOW));}}),
}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_BOW_CHEST, {[]{return true;}}),
LocationAccess(FOREST_TEMPLE_MQ_MAP_CHEST, {[]{return IsAdult && CanUse(BOW);}}),
LocationAccess(FOREST_TEMPLE_MQ_COMPASS_CHEST, {[]{return IsAdult && CanUse(BOW);}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_BOW_CHEST, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_MAP_CHEST, {[]{return IsAdult && CanUse(RG_FAIRY_BOW);}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_COMPASS_CHEST, {[]{return IsAdult && CanUse(RG_FAIRY_BOW);}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_MQ_FALLING_ROOM, {[]{return SmallKeys(FOREST_TEMPLE, 5) && ((IsAdult && CanUse(BOW)) || CanUse(DINS_FIRE));}}),
Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, {[]{return SmallKeys(RR_FOREST_TEMPLE, 5) && ((IsAdult && CanUse(RG_FAIRY_BOW)) || CanUse(RG_DINS_FIRE));}}),
});
areaTable[FOREST_TEMPLE_MQ_FALLING_ROOM] = Area("Forest Temple MQ Falling Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_FOREST_TEMPLE_MQ_FALLING_ROOM] = Area("Forest Temple MQ Falling Room", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ForestTempleAmyAndMeg, {[]{return ForestTempleAmyAndMeg || (IsAdult && CanUse(BOW) && SmallKeys(FOREST_TEMPLE, 6));}}),
EventAccess(&ForestTempleAmyAndMeg, {[]{return ForestTempleAmyAndMeg || (IsAdult && CanUse(RG_FAIRY_BOW) && SmallKeys(RR_FOREST_TEMPLE, 6));}}),
}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE, {[]{return true;}}),
});
areaTable[FOREST_TEMPLE_MQ_BOSS_REGION] = Area("Forest Temple MQ Boss Region", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_FOREST_TEMPLE_MQ_BOSS_REGION] = Area("Forest Temple MQ Boss Region", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(FOREST_TEMPLE_MQ_BASEMENT_CHEST, {[]{return true;}}),
LocationAccess(RC_FOREST_TEMPLE_MQ_BASEMENT_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyForestTemple;}}),
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyForestTemple;}}),
});
}
/*---------------------------
| BOSS ROOM |
---------------------------*/
areaTable[FOREST_TEMPLE_BOSS_ENTRYWAY] =
Area("Forest Temple Boss Entryway", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_FOREST_TEMPLE_BOSS_ENTRYWAY] =
Area("Forest Temple Boss Entryway", "Forest Temple", RHT_FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(FOREST_TEMPLE_BOSS_REGION, { [] { return Dungeon::ForestTemple.IsVanilla() && false; } }),
Entrance(FOREST_TEMPLE_MQ_BOSS_REGION, { [] { return Dungeon::ForestTemple.IsMQ() && false; } }),
Entrance(FOREST_TEMPLE_BOSS_ROOM, { [] { return true; } }),
Entrance(RR_FOREST_TEMPLE_BOSS_REGION, { [] { return Dungeon::ForestTemple.IsVanilla() && false; } }),
Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, { [] { return Dungeon::ForestTemple.IsMQ() && false; } }),
Entrance(RR_FOREST_TEMPLE_BOSS_ROOM, { [] { return true; } }),
});
areaTable[FOREST_TEMPLE_BOSS_ROOM] = Area(
"Forest Temple Boss Room", "Forest Temple", NONE, NO_DAY_NIGHT_CYCLE,
areaTable[RR_FOREST_TEMPLE_BOSS_ROOM] = Area(
"Forest Temple Boss Room", "Forest Temple", RHT_NONE, NO_DAY_NIGHT_CYCLE,
{
// Events
EventAccess(&ForestTempleClear, { [] {
return ForestTempleClear || (HasBossSoul(PHANTOM_GANON_BOSS_SOUL) && ((CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) &&
(CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT))));
return ForestTempleClear || (HasBossSoul(RG_PHANTOM_GANON_SOUL) && ((CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) &&
(CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT))));
} }),
},
{
// Locations
LocationAccess(FOREST_TEMPLE_PHANTOM_GANON_HEART, { [] { return ForestTempleClear; } }),
LocationAccess(PHANTOM_GANON, { [] { return ForestTempleClear; } }),
LocationAccess(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, { [] { return ForestTempleClear; } }),
LocationAccess(RC_PHANTOM_GANON, { [] { return ForestTempleClear; } }),
},
{
// Exits
Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
});
}

View File

@@ -11,203 +11,203 @@ void AreaTable_Init_GanonsCastle() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[GANONS_CASTLE_ENTRYWAY] = Area("Ganon's Castle Entryway", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_GANONS_CASTLE_ENTRYWAY] = Area("Ganon's Castle Entryway", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GANONS_CASTLE_LOBBY, {[]{return Dungeon::GanonsCastle.IsVanilla();}}),
Entrance(GANONS_CASTLE_MQ_LOBBY, {[]{return Dungeon::GanonsCastle.IsMQ();}}),
Entrance(CASTLE_GROUNDS_FROM_GANONS_CASTLE, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_LOBBY, {[]{return Dungeon::GanonsCastle.IsVanilla();}}),
Entrance(RR_GANONS_CASTLE_MQ_LOBBY, {[]{return Dungeon::GanonsCastle.IsMQ();}}),
Entrance(RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::GanonsCastle.IsVanilla()) {
areaTable[GANONS_CASTLE_LOBBY] = Area("Ganon's Castle Lobby", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_GANONS_CASTLE_LOBBY] = Area("Ganon's Castle Lobby", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GANONS_CASTLE_ENTRYWAY, {[]{return true;}}),
Entrance(GANONS_CASTLE_FOREST_TRIAL, {[]{return true;}}),
Entrance(GANONS_CASTLE_FIRE_TRIAL, {[]{return true;}}),
Entrance(GANONS_CASTLE_WATER_TRIAL, {[]{return true;}}),
Entrance(GANONS_CASTLE_SHADOW_TRIAL, {[]{return true;}}),
Entrance(GANONS_CASTLE_SPIRIT_TRIAL, {[]{return true;}}),
Entrance(GANONS_CASTLE_LIGHT_TRIAL, {[]{return CanUse(GOLDEN_GAUNTLETS);}}),
Entrance(GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || Trial::ForestTrial.IsSkipped()) &&
Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_FOREST_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_FIRE_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_WATER_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_SHADOW_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL, {[]{return CanUse(RG_GOLDEN_GAUNTLETS);}}),
Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || Trial::ForestTrial.IsSkipped()) &&
(FireTrialClear || Trial::FireTrial.IsSkipped()) &&
(WaterTrialClear || Trial::WaterTrial.IsSkipped()) &&
(ShadowTrialClear || Trial::ShadowTrial.IsSkipped()) &&
(SpiritTrialClear || Trial::SpiritTrial.IsSkipped()) &&
(LightTrialClear || Trial::LightTrial.IsSkipped());}}),
Entrance(GANONS_CASTLE_DEKU_SCRUBS, {[]{return LogicLensCastle || CanUse(LENS_OF_TRUTH);}}),
Entrance(RR_GANONS_CASTLE_DEKU_SCRUBS, {[]{return LogicLensCastle || CanUse(RG_LENS_OF_TRUTH);}}),
});
areaTable[GANONS_CASTLE_DEKU_SCRUBS] = Area("Ganon's Castle Deku Scrubs", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_DEKU_SCRUBS] = Area("Ganon's Castle Deku Scrubs", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FreeFairies, {[]{return true;}}),
}, {
//Locations
LocationAccess(GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(GANONS_CASTLE_DEKU_SCRUB_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(GANONS_CASTLE_DEKU_SCRUB_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GANONS_CASTLE_DEKU_SCRUB_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GANONS_CASTLE_DEKU_SCRUB_LEFT, {[]{return CanStunDeku;}}),
}, {});
areaTable[GANONS_CASTLE_FOREST_TRIAL] = Area("Ganon's Castle Forest Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_FOREST_TRIAL] = Area("Ganon's Castle Forest Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ForestTrialClear, {[]{return CanUse(LIGHT_ARROWS) && (FireArrows || DinsFire);}}),
EventAccess(&ForestTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && (FireArrows || DinsFire);}}),
}, {
//Locations
LocationAccess(GANONS_CASTLE_FOREST_TRIAL_CHEST, {[]{return IsAdult || CanChildDamage;}}),
LocationAccess(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, {[]{return IsAdult || CanChildDamage;}}),
}, {});
areaTable[GANONS_CASTLE_FIRE_TRIAL] = Area("Ganon's Castle Fire Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_FIRE_TRIAL] = Area("Ganon's Castle Fire Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FireTrialClear, {[]{return CanUse(GORON_TUNIC) && CanUse(GOLDEN_GAUNTLETS) && CanUse(LIGHT_ARROWS) && CanUse(LONGSHOT);}}),
EventAccess(&FireTrialClear, {[]{return CanUse(RG_GORON_TUNIC) && CanUse(RG_GOLDEN_GAUNTLETS) && CanUse(RG_LIGHT_ARROWS) && CanUse(RG_LONGSHOT);}}),
}, {}, {});
areaTable[GANONS_CASTLE_WATER_TRIAL] = Area("Ganon's Castle Water Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_WATER_TRIAL] = Area("Ganon's Castle Water Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&BlueFireAccess, {[]{return BlueFireAccess || HasBottle;}}),
EventAccess(&FairyPot, {[]{return FairyPot || BlueFire;}}),
EventAccess(&WaterTrialClear, {[]{return BlueFire && Hammer && CanUse(LIGHT_ARROWS);}}),
EventAccess(&WaterTrialClear, {[]{return BlueFire && Hammer && CanUse(RG_LIGHT_ARROWS);}}),
}, {
//Locations
LocationAccess(GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, {[]{return true;}}),
LocationAccess(GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, {[]{return true;}}),
}, {});
areaTable[GANONS_CASTLE_SHADOW_TRIAL] = Area("Ganon's Castle Shadow Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_SHADOW_TRIAL] = Area("Ganon's Castle Shadow Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ShadowTrialClear, {[]{return CanUse(LIGHT_ARROWS) && Hammer && ((FireArrows && (LogicLensCastle || CanUse(LENS_OF_TRUTH))) || (CanUse(LONGSHOT) && (CanUse(HOVER_BOOTS) || (DinsFire && (LogicLensCastle || CanUse(LENS_OF_TRUTH))))));}}),
EventAccess(&ShadowTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && Hammer && ((FireArrows && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH))) || (CanUse(RG_LONGSHOT) && (CanUse(RG_HOVER_BOOTS) || (DinsFire && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH))))));}}),
}, {
//Locations
LocationAccess(GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, {[]{return CanUse(FIRE_ARROWS) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || CanPlay(SongOfTime) || IsChild;}}),
LocationAccess(GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return CanUse(FIRE_ARROWS) || (CanUse(LONGSHOT) && (CanUse(HOVER_BOOTS) || CanUse(DINS_FIRE)));}}),
LocationAccess(RC_GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST, {[]{return CanUse(RG_FIRE_ARROWS) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || CanPlay(SongOfTime) || IsChild;}}),
LocationAccess(RC_GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return CanUse(RG_FIRE_ARROWS) || (CanUse(RG_LONGSHOT) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_DINS_FIRE)));}}),
}, {});
areaTable[GANONS_CASTLE_SPIRIT_TRIAL] = Area("Ganon's Castle Spirit Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL] = Area("Ganon's Castle Spirit Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&NutPot, {[]{return NutPot || ((LogicSpiritTrialHookshot || CanUse(HOOKSHOT)) && HasBombchus && Bow && (MirrorShield || (SunlightArrows && CanUse(LIGHT_ARROWS))) && IsAdult);}}),
EventAccess(&SpiritTrialClear, {[]{return CanUse(LIGHT_ARROWS) && (MirrorShield || SunlightArrows) && HasBombchus && (LogicSpiritTrialHookshot || CanUse(HOOKSHOT));}}),
EventAccess(&NutPot, {[]{return NutPot || ((LogicSpiritTrialHookshot || CanUse(RG_HOOKSHOT)) && HasBombchus && Bow && (MirrorShield || (SunlightArrows && CanUse(RG_LIGHT_ARROWS))) && IsAdult);}}),
EventAccess(&SpiritTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && (MirrorShield || SunlightArrows) && HasBombchus && (LogicSpiritTrialHookshot || CanUse(RG_HOOKSHOT));}}),
}, {
//Locations
LocationAccess(GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, {[]{return LogicSpiritTrialHookshot || CanUse(HOOKSHOT);}}),
LocationAccess(GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return (LogicSpiritTrialHookshot || CanUse(HOOKSHOT)) && HasBombchus && (LogicLensCastle || CanUse(LENS_OF_TRUTH));}}),
LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST, {[]{return LogicSpiritTrialHookshot || CanUse(RG_HOOKSHOT);}}),
LocationAccess(RC_GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return (LogicSpiritTrialHookshot || CanUse(RG_HOOKSHOT)) && HasBombchus && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH));}}),
}, {});
areaTable[GANONS_CASTLE_LIGHT_TRIAL] = Area("Ganon's Castle Light Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL] = Area("Ganon's Castle Light Trial", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&LightTrialClear, {[]{return CanUse(LIGHT_ARROWS) && CanUse(HOOKSHOT) && SmallKeys(GANONS_CASTLE, 2) && (LogicLensCastle || CanUse(LENS_OF_TRUTH));}}),
EventAccess(&LightTrialClear, {[]{return CanUse(RG_LIGHT_ARROWS) && CanUse(RG_HOOKSHOT) && SmallKeys(RR_GANONS_CASTLE, 2) && (LogicLensCastle || CanUse(RG_LENS_OF_TRUTH));}}),
}, {
//Locations
LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, {[]{return true;}}),
LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, {[]{return true;}}),
LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, {[]{return true;}}),
LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, {[]{return LogicLensCastle || CanUse(LENS_OF_TRUTH);}}),
LocationAccess(GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(GANONS_CASTLE, 1);}}),
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST, {[]{return LogicLensCastle || CanUse(RG_LENS_OF_TRUTH);}}),
LocationAccess(RC_GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(RR_GANONS_CASTLE, 1);}}),
}, {});
}
areaTable[GANONS_CASTLE_TOWER] = Area("Ganon's Castle Tower", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GANONS_CASTLE_TOWER] = Area("Ganon's Castle Tower", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GANONS_TOWER_BOSS_KEY_CHEST, {[]{return true;}}),
LocationAccess(GANONDORF_HINT, {[]{return BossKeyGanonsCastle;}}),
LocationAccess(GANON, {[]{return HasBossSoul(GANON_BOSS_SOUL) && BossKeyGanonsCastle && CanUse(LIGHT_ARROWS);}}),
LocationAccess(RC_GANONS_TOWER_BOSS_KEY_CHEST, {[]{return true;}}),
LocationAccess(RC_GANONDORF_HINT, {[]{return BossKeyGanonsCastle;}}),
LocationAccess(RC_GANON, {[]{return HasBossSoul(RG_GANON_SOUL) && BossKeyGanonsCastle && CanUse(RG_LIGHT_ARROWS);}}),
}, {});
/*---------------------------
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::GanonsCastle.IsMQ()) {
areaTable[GANONS_CASTLE_MQ_LOBBY] = Area("Ganon's Castle MQ Lobby", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_GANONS_CASTLE_MQ_LOBBY] = Area("Ganon's Castle MQ Lobby", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GANONS_CASTLE_ENTRYWAY, {[]{return (IsAdult || (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword))));}}),
Entrance(GANONS_CASTLE_MQ_FOREST_TRIAL, {[]{return true;}}),
Entrance(GANONS_CASTLE_MQ_FIRE_TRIAL, {[]{return true;}}),
Entrance(GANONS_CASTLE_MQ_WATER_TRIAL, {[]{return true;}}),
Entrance(GANONS_CASTLE_MQ_SHADOW_TRIAL, {[]{return true;}}),
Entrance(GANONS_CASTLE_MQ_SPIRIT_TRIAL, {[]{return true;}}),
Entrance(GANONS_CASTLE_MQ_LIGHT_TRIAL, {[]{return CanUse(GOLDEN_GAUNTLETS);}}),
Entrance(GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || Trial::ForestTrial.IsSkipped()) &&
Entrance(RR_GANONS_CASTLE_ENTRYWAY, {[]{return (IsAdult || (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword))));}}),
Entrance(RR_GANONS_CASTLE_MQ_FOREST_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_MQ_FIRE_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_MQ_WATER_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL, {[]{return true;}}),
Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL, {[]{return CanUse(RG_GOLDEN_GAUNTLETS);}}),
Entrance(RR_GANONS_CASTLE_TOWER, {[]{return (ForestTrialClear || Trial::ForestTrial.IsSkipped()) &&
(FireTrialClear || Trial::FireTrial.IsSkipped()) &&
(WaterTrialClear || Trial::WaterTrial.IsSkipped()) &&
(ShadowTrialClear || Trial::ShadowTrial.IsSkipped()) &&
(SpiritTrialClear || Trial::SpiritTrial.IsSkipped()) &&
(LightTrialClear || Trial::LightTrial.IsSkipped());}}),
Entrance(GANONS_CASTLE_MQ_DEKU_SCRUBS, {[]{return LogicLensCastleMQ || CanUse(LENS_OF_TRUTH);}}),
Entrance(RR_GANONS_CASTLE_MQ_DEKU_SCRUBS, {[]{return LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH);}}),
});
areaTable[GANONS_CASTLE_MQ_DEKU_SCRUBS] = Area("Ganon's Castle MQ Deku Scrubs", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_MQ_DEKU_SCRUBS] = Area("Ganon's Castle MQ Deku Scrubs", "Ganon's Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FreeFairies, {[]{return true;}}),
}, {
//Locations
LocationAccess(GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, {[]{return CanStunDeku;}}),
LocationAccess(GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER, {[]{return CanStunDeku;}}),
LocationAccess(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT, {[]{return CanStunDeku;}}),
}, {});
areaTable[GANONS_CASTLE_MQ_FOREST_TRIAL] = Area("Ganon's Castle MQ Forest Trial", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_MQ_FOREST_TRIAL] = Area("Ganon's Castle MQ Forest Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ForestTrialClear, {[]{return IsAdult && CanUse(LIGHT_ARROWS) && CanPlay(SongOfTime);}}),
EventAccess(&ForestTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && CanPlay(SongOfTime);}}),
}, {
//Locations
LocationAccess(GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, {[]{return (IsAdult && CanUse(BOW)) || (IsChild && CanUse(SLINGSHOT));}}),
LocationAccess(GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, {[]{return HasFireSource;}}),
LocationAccess(GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, {[]{return HookshotOrBoomerang;}}),
LocationAccess(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST, {[]{return (IsAdult && CanUse(RG_FAIRY_BOW)) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));}}),
LocationAccess(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST, {[]{return HasFireSource;}}),
LocationAccess(RC_GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY, {[]{return HookshotOrBoomerang;}}),
}, {});
areaTable[GANONS_CASTLE_MQ_FIRE_TRIAL] = Area("Ganon's Castle MQ Fire Trial", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL] = Area("Ganon's Castle MQ Fire Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FireTrialClear, {[]{return CanUse(GORON_TUNIC) && CanUse(GOLDEN_GAUNTLETS) && CanUse(LIGHT_ARROWS) && (CanUse(LONGSHOT) || HoverBoots || (LogicFireTrialMQ && CanUse(HOOKSHOT)));}}),
//Trick: CanUse(GORON_TUNIC) && CanUse(GOLDEN_GAUNTLETS) && CanUse(LIGHT_ARROWS) && (CanUse(LONGSHOT) || HoverBoots || (LogicFireTrialMQ && CanUse(HOOKSHOT)))
EventAccess(&FireTrialClear, {[]{return CanUse(RG_GORON_TUNIC) && CanUse(RG_GOLDEN_GAUNTLETS) && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_LONGSHOT) || HoverBoots || (LogicFireTrialMQ && CanUse(RG_HOOKSHOT)));}}),
//Trick: CanUse(RG_GORON_TUNIC) && CanUse(RG_GOLDEN_GAUNTLETS) && CanUse(RG_LIGHT_ARROWS) && (CanUse(RG_LONGSHOT) || HoverBoots || (LogicFireTrialMQ && CanUse(RG_HOOKSHOT)))
}, {}, {});
areaTable[GANONS_CASTLE_MQ_WATER_TRIAL] = Area("Ganon's Castle MQ Water Trial", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL] = Area("Ganon's Castle MQ Water Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&WaterTrialClear, {[]{return BlueFire && IsAdult && CanUse(LIGHT_ARROWS) && SmallKeys(GANONS_CASTLE, 3);}}),
EventAccess(&WaterTrialClear, {[]{return BlueFire && IsAdult && CanUse(RG_LIGHT_ARROWS) && SmallKeys(RR_GANONS_CASTLE, 3);}}),
EventAccess(&BlueFireAccess, {[]{return BlueFireAccess || HasBottle;}}),
}, {
//Locations
LocationAccess(GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, {[]{return BlueFire && (IsAdult || CanUse(STICKS) || KokiriSword || CanUseProjectile);}}),
LocationAccess(RC_GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, {[]{return BlueFire && (IsAdult || CanUse(RG_STICKS) || KokiriSword || CanUseProjectile);}}),
}, {});
areaTable[GANONS_CASTLE_MQ_SHADOW_TRIAL] = Area("Ganon's Castle MQ Shadow Trial", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL] = Area("Ganon's Castle MQ Shadow Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ShadowTrialClear, {[]{return IsAdult && CanUse(LIGHT_ARROWS) && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)));}}),
//Trick: IsAdult && CanUse(LIGHT_ARROWS) && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)))
EventAccess(&ShadowTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)));}}),
//Trick: IsAdult && CanUse(RG_LIGHT_ARROWS) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)))
}, {
//Locations
LocationAccess(GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, {[]{return IsAdult && ((Bow && (CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS))) || (CanUse(HOVER_BOOTS) && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH)) && (HasExplosives || GoronBracelet || CanUse(DINS_FIRE))));}}),
LocationAccess(GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, {[]{return IsAdult && Bow && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)));}}),
//Trick: IsAdult && Bow && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)))
LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST, {[]{return IsAdult && ((Bow && (CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS))) || (CanUse(RG_HOVER_BOOTS) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HasExplosives || GoronBracelet || CanUse(RG_DINS_FIRE))));}}),
LocationAccess(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, {[]{return IsAdult && Bow && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)));}}),
//Trick: IsAdult && Bow && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (HoverBoots || (Hookshot && (HasFireSource || LogicShadowTrialMQ)))
}, {});
areaTable[GANONS_CASTLE_MQ_SPIRIT_TRIAL] = Area("Ganon's Castle MQ Spirit Castle", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL] = Area("Ganon's Castle MQ Spirit Castle", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&SpiritTrialClear, {[]{return IsAdult && CanUse(LIGHT_ARROWS) && Hammer && HasBombchus && ((FireArrows && MirrorShield) || SunlightArrows);}}),
EventAccess(&NutPot, {[]{return NutPot || (Hammer && HasBombchus && IsAdult && ((CanUse(FIRE_ARROWS) && MirrorShield) || (SunlightArrows && CanUse(LIGHT_ARROWS))));}}),
EventAccess(&SpiritTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && Hammer && HasBombchus && ((FireArrows && MirrorShield) || SunlightArrows);}}),
EventAccess(&NutPot, {[]{return NutPot || (Hammer && HasBombchus && IsAdult && ((CanUse(RG_FIRE_ARROWS) && MirrorShield) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS))));}}),
}, {
//Locations
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, {[]{return IsAdult && (Bow || LogicRustedSwitches) && Hammer;}}),
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return IsAdult && (Bow || LogicRustedSwitches) && Hammer && HasBombchus && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH));}}),
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(FIRE_ARROWS) && CanUse(MIRROR_SHIELD)) || (SunlightArrows && CanUse(LIGHT_ARROWS)));}}),
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(FIRE_ARROWS) && CanUse(MIRROR_SHIELD)) || (SunlightArrows && CanUse(LIGHT_ARROWS)));}}),
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(FIRE_ARROWS) && CanUse(MIRROR_SHIELD)) || (SunlightArrows && CanUse(LIGHT_ARROWS)));}}),
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(FIRE_ARROWS) && CanUse(MIRROR_SHIELD)) || (SunlightArrows && CanUse(LIGHT_ARROWS)));}}),
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, {[]{return IsAdult && (Bow || LogicRustedSwitches) && Hammer;}}),
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return IsAdult && (Bow || LogicRustedSwitches) && Hammer && HasBombchus && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}),
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}),
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}),
LocationAccess(RC_GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && ((CanUse(RG_FIRE_ARROWS) && CanUse(RG_MIRROR_SHIELD)) || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}),
}, {});
areaTable[GANONS_CASTLE_MQ_LIGHT_TRIAL] = Area("Ganon's Castle MQ Light Trial", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GANONS_CASTLE_MQ_LIGHT_TRIAL] = Area("Ganon's Castle MQ Light Trial", "Ganons Castle", RHT_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&LightTrialClear, {[]{return IsAdult && CanUse(LIGHT_ARROWS) && SmallKeys(GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH)) && (Hookshot || LogicLightTrialMQ);}}),
//Trick: IsAdult && CanUse(LIGHT_ARROWS) && SmallKeys(GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH)) && (Hookshot || LogicLightTrialMQ)
EventAccess(&LightTrialClear, {[]{return IsAdult && CanUse(RG_LIGHT_ARROWS) && SmallKeys(RR_GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (Hookshot || LogicLightTrialMQ);}}),
//Trick: IsAdult && CanUse(RG_LIGHT_ARROWS) && SmallKeys(RR_GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(RG_LENS_OF_TRUTH)) && (Hookshot || LogicLightTrialMQ)
}, {
//Locations
LocationAccess(GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
}, {});
}
}

View File

@@ -10,104 +10,104 @@ void AreaTable_Init_GerudoTrainingGrounds() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[GERUDO_TRAINING_GROUNDS_ENTRYWAY] = Area("Gerudo Training Grounds Entryway", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY] = Area("Gerudo Training Grounds Entryway", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_LOBBY, {[]{return Dungeon::GerudoTrainingGrounds.IsVanilla();}}),
Entrance(GERUDO_TRAINING_GROUNDS_MQ_LOBBY, {[]{return Dungeon::GerudoTrainingGrounds.IsMQ();}}),
Entrance(GERUDO_FORTRESS, {[]{return true;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_LOBBY, {[]{return Dungeon::GerudoTrainingGrounds.IsVanilla();}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY, {[]{return Dungeon::GerudoTrainingGrounds.IsMQ();}}),
Entrance(RR_GERUDO_FORTRESS, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::GerudoTrainingGrounds.IsVanilla()) {
areaTable[GERUDO_TRAINING_GROUNDS_LOBBY] = Area("Gerudo Training Grounds Lobby", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_LOBBY] = Area("Gerudo Training Grounds Lobby", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_LOBBY_LEFT_CHEST, {[]{return CanUse(BOW) || CanUse(SLINGSHOT);}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_LOBBY_RIGHT_CHEST, {[]{return CanUse(BOW) || CanUse(SLINGSHOT);}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_STALFOS_CHEST, {[]{return IsAdult || KokiriSword;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_BEAMOS_CHEST, {[]{return HasExplosives && (IsAdult || KokiriSword);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_LOBBY_LEFT_CHEST, {[]{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_LOBBY_RIGHT_CHEST, {[]{return CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_STALFOS_CHEST, {[]{return IsAdult || KokiriSword;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_BEAMOS_CHEST, {[]{return HasExplosives && (IsAdult || KokiriSword);}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return true;}}),
Entrance(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM, {[]{return (IsAdult || KokiriSword) && (CanUse(HOOKSHOT) || LogicGtgWithoutHookshot);}}),
Entrance(GERUDO_TRAINING_GROUNDS_LAVA_ROOM, {[]{return Here(GERUDO_TRAINING_GROUNDS_LOBBY, []{return (IsAdult || KokiriSword) && HasExplosives;});}}),
Entrance(GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE, {[]{return true;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return true;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM, {[]{return (IsAdult || KokiriSword) && (CanUse(RG_HOOKSHOT) || LogicGtgWithoutHookshot);}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_LAVA_ROOM, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_LOBBY, []{return (IsAdult || KokiriSword) && HasExplosives;});}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE, {[]{return true;}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE] = Area("Gerudo Training Grounds Central Maze", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE] = Area("Gerudo Training Grounds Central Maze", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_HIDDEN_CEILING_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 3) && (LogicLensGtg || CanUse(LENS_OF_TRUTH));}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MAZE_PATH_FIRST_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 4);}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MAZE_PATH_SECOND_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 6);}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MAZE_PATH_THIRD_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 7);}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MAZE_PATH_FINAL_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 9);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_HIDDEN_CEILING_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 3) && (LogicLensGtg || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FIRST_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 4);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_SECOND_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 6);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_THIRD_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 7);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_PATH_FINAL_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 9);}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 9);}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 9);}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT] = Area("Gerudo Training Grounds Central Maze Right", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT] = Area("Gerudo Training Grounds Central Maze Right", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_MAZE_RIGHT_CENTRAL_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MAZE_RIGHT_SIDE_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_FREESTANDING_KEY, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, {[]{return true;}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, {[]{return CanUse(HOOKSHOT);}}),
Entrance(GERUDO_TRAINING_GROUNDS_LAVA_ROOM, {[]{return true;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, {[]{return CanUse(RG_HOOKSHOT);}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_LAVA_ROOM, {[]{return true;}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_LAVA_ROOM] = Area("Gerudo Training Grounds Lava Room", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_LAVA_ROOM] = Area("Gerudo Training Grounds Lava Room", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_UNDERWATER_SILVER_RUPEE_CHEST, {[]{return CanUse(HOOKSHOT) && CanPlay(SongOfTime) && IronBoots && WaterTimer >= 24;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, {[]{return CanUse(RG_HOOKSHOT) && CanPlay(SongOfTime) && IronBoots && WaterTimer >= 24;}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, {[]{return CanPlay(SongOfTime) || IsChild;}}),
Entrance(GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, {[]{return CanUse(LONGSHOT) || (CanUse(HOVER_BOOTS) && CanUse(HOOKSHOT));}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, {[]{return CanPlay(SongOfTime) || IsChild;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, {[]{return CanUse(RG_LONGSHOT) || (CanUse(RG_HOVER_BOOTS) && CanUse(RG_HOOKSHOT));}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_HAMMER_ROOM] = Area("Gerudo Training Grounds Hammer Room", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_HAMMER_ROOM] = Area("Gerudo Training Grounds Hammer Room", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_HAMMER_ROOM_CLEAR_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_HAMMER_ROOM_SWITCH_CHEST, {[]{return CanUse(MEGATON_HAMMER) || (CanTakeDamage && LogicFlamingChests);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_CLEAR_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_HAMMER_ROOM_SWITCH_CHEST, {[]{return CanUse(RG_MEGATON_HAMMER) || (CanTakeDamage && LogicFlamingChests);}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, {[]{return CanUse(MEGATON_HAMMER) && Bow;}}),
Entrance(GERUDO_TRAINING_GROUNDS_LAVA_ROOM, {[]{return true;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, {[]{return CanUse(RG_MEGATON_HAMMER) && Bow;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_LAVA_ROOM, {[]{return true;}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER] = Area("Gerudo Training Grounds Eye Statue Lower", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER] = Area("Gerudo Training Grounds Eye Statue Lower", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_EYE_STATUE_CHEST, {[]{return CanUse(BOW);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_EYE_STATUE_CHEST, {[]{return CanUse(RG_FAIRY_BOW);}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, {[]{return true;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, {[]{return true;}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER] = Area("Gerudo Training Grounds Eye Statue Upper", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER] = Area("Gerudo Training Grounds Eye Statue Upper", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_NEAR_SCARECROW_CHEST, {[]{return CanUse(BOW);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_NEAR_SCARECROW_CHEST, {[]{return CanUse(RG_FAIRY_BOW);}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, {[]{return true;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, {[]{return true;}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM] = Area("Gerudo Training Grounds Heavy Block Room", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM] = Area("Gerudo Training Grounds Heavy Block Room", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_BEFORE_HEAVY_BLOCK_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_BEFORE_HEAVY_BLOCK_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER, {[]{return (LogicLensGtg || CanUse(LENS_OF_TRUTH)) && (CanUse(HOOKSHOT) || (LogicGtgFakeWall && CanUse(HOVER_BOOTS)));}}),
Entrance(GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM, {[]{return (LogicLensGtg || CanUse(LENS_OF_TRUTH)) && (CanUse(HOOKSHOT) || (LogicGtgFakeWall && CanUse(HOVER_BOOTS))) && CanUse(SILVER_GAUNTLETS);}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER, {[]{return (LogicLensGtg || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOOKSHOT) || (LogicGtgFakeWall && CanUse(RG_HOVER_BOOTS)));}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM, {[]{return (LogicLensGtg || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOOKSHOT) || (LogicGtgFakeWall && CanUse(RG_HOVER_BOOTS))) && CanUse(RG_SILVER_GAUNTLETS);}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM] = Area("Gerudo Training Grounds Like Like Room", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM] = Area("Gerudo Training Grounds Like Like Room", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_FIRST_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_SECOND_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_THIRD_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_FOURTH_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FIRST_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_SECOND_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_THIRD_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_FOURTH_CHEST, {[]{return true;}}),
}, {});
}
@@ -115,79 +115,79 @@ void AreaTable_Init_GerudoTrainingGrounds() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::GerudoTrainingGrounds.IsMQ()) {
areaTable[GERUDO_TRAINING_GROUNDS_MQ_LOBBY] = Area("Gerudo Training Grounds MQ Lobby", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY] = Area("Gerudo Training Grounds MQ Lobby", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_LOBBY_LEFT_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_LOBBY_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_HIDDEN_CEILING_CHEST, {[]{return LogicLensGtgMQ || CanUse(LENS_OF_TRUTH);}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_MAZE_PATH_FIRST_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_MAZE_PATH_SECOND_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_MAZE_PATH_THIRD_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 1);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_LEFT_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_LOBBY_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HIDDEN_CEILING_CHEST, {[]{return LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_FIRST_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_SECOND_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_PATH_THIRD_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 1);}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return true;}}),
Entrance(GERUDO_TRAINING_GROUNDS_MQ_LEFT_SIDE, {[]{return Here(GERUDO_TRAINING_GROUNDS_MQ_LOBBY, []{return HasFireSource;});}}),
Entrance(GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE, {[]{return Here(GERUDO_TRAINING_GROUNDS_MQ_LOBBY, []{return (IsAdult && CanUse(BOW)) || (IsChild && CanUse(SLINGSHOT));});}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return true;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_LEFT_SIDE, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY, []{return HasFireSource;});}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE, {[]{return Here(RR_GERUDO_TRAINING_GROUNDS_MQ_LOBBY, []{return (IsAdult && CanUse(RG_FAIRY_BOW)) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT));});}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE] = Area("Gerudo Training Grounds MQ Right Side", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE] = Area("Gerudo Training Grounds MQ Right Side", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {
//Events
//EventAccess(&WallFairy, {[]{return WallFairy || (IsAdult && CanUse(BOW));}}),
//EventAccess(&WallFairy, {[]{return WallFairy || (IsAdult && CanUse(RG_FAIRY_BOW));}}),
}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_DINOLFOS_CHEST, {[]{return IsAdult;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_CHEST, {[]{return IsAdult;}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER, {[]{return (Bow || CanUse(LONGSHOT)) && CanUse(HOVER_BOOTS) && IsAdult;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER, {[]{return (Bow || CanUse(RG_LONGSHOT)) && CanUse(RG_HOVER_BOOTS) && IsAdult;}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER] = Area("Gerudo Training Grounds MQ Underwater", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER] = Area("Gerudo Training Grounds MQ Underwater", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER_SILVER_RUPEE_CHEST, {[]{return HasFireSource && IsAdult && CanUse(IRON_BOOTS) && WaterTimer >= 24 && CanTakeDamage;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, {[]{return HasFireSource && IsAdult && CanUse(RG_IRON_BOOTS) && WaterTimer >= 24 && CanTakeDamage;}}),
}, {});
areaTable[GERUDO_TRAINING_GROUNDS_MQ_LEFT_SIDE] = Area("Gerudo Training Grounds MQ Left Side", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_LEFT_SIDE] = Area("Gerudo Training Grounds MQ Left Side", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_FIRST_IRON_KNUCKLE_CHEST, {[]{return IsAdult || KokiriSword || HasExplosives;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_FIRST_IRON_KNUCKLE_CHEST, {[]{return IsAdult || KokiriSword || HasExplosives;}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, {[]{return (IsAdult && CanUse(LONGSHOT)) || LogicGtgMQWithoutHookshot || (LogicGtgMQWithHookshot && IsAdult && CanUse(HOOKSHOT));}}),
//Trick: (IsAdult && CanUse(LONGSHOT)) || LogicGtgMQWithoutHookshot || (LogicGtgMQWithHookshot && IsAdult && CanUse(HOOKSHOT))
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, {[]{return (IsAdult && CanUse(RG_LONGSHOT)) || LogicGtgMQWithoutHookshot || (LogicGtgMQWithHookshot && IsAdult && CanUse(RG_HOOKSHOT));}}),
//Trick: (IsAdult && CanUse(RG_LONGSHOT)) || LogicGtgMQWithoutHookshot || (LogicGtgMQWithHookshot && IsAdult && CanUse(RG_HOOKSHOT))
});
areaTable[GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM] = Area("Gerudo Training Grounds MQ Stalfos Room", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM] = Area("Gerudo Training Grounds MQ Stalfos Room", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&BlueFireAccess, {[]{return BlueFireAccess || HasBottle;}}),
}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_BEFORE_HEAVY_BLOCK_CHEST, {[]{return IsAdult;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_HEAVY_BLOCK_CHEST, {[]{return CanUse(SILVER_GAUNTLETS);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_BEFORE_HEAVY_BLOCK_CHEST, {[]{return IsAdult;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, {[]{return CanUse(RG_SILVER_GAUNTLETS);}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, {[]{return IsAdult && (LogicLensGtgMQ || CanUse(LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (LogicGtgFakeWall && IsAdult && CanUse(HOVER_BOOTS)));}}),
//Trick: IsAdult && (LogicLensGtgMQ || CanUse(LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (LogicGtgFakeWall && IsAdult && CanUse(HOVER_BOOTS)))
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, {[]{return IsAdult && (LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (LogicGtgFakeWall && IsAdult && CanUse(RG_HOVER_BOOTS)));}}),
//Trick: IsAdult && (LogicLensGtgMQ || CanUse(RG_LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (LogicGtgFakeWall && IsAdult && CanUse(RG_HOVER_BOOTS)))
});
areaTable[GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS] = Area("Gerudo Training Grounds MQ Back Areas", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS] = Area("Gerudo Training Grounds MQ Back Areas", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_EYE_STATUE_CHEST, {[]{return Bow;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_SECOND_IRON_KNUCKLE_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_FLAME_CIRCLE_CHEST, {[]{return CanUse(HOOKSHOT) || Bow || HasExplosives;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_EYE_STATUE_CHEST, {[]{return Bow;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_SECOND_IRON_KNUCKLE_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_FLAME_CIRCLE_CHEST, {[]{return CanUse(RG_HOOKSHOT) || Bow || HasExplosives;}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_MQ_CENTRAL_MAZE_RIGHT, {[]{return Hammer;}}),
Entrance(GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE, {[]{return CanUse(LONGSHOT);}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_CENTRAL_MAZE_RIGHT, {[]{return Hammer;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE, {[]{return CanUse(RG_LONGSHOT);}}),
});
areaTable[GERUDO_TRAINING_GROUNDS_MQ_CENTRAL_MAZE_RIGHT] = Area("Gerudo Training Grounds MQ Central Maze Right", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GERUDO_TRAINING_GROUNDS_MQ_CENTRAL_MAZE_RIGHT] = Area("Gerudo Training Grounds MQ Central Maze Right", "Gerudo Training Grounds", RHT_GERUDO_TRAINING_GROUND, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_MAZE_RIGHT_CENTRAL_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_MAZE_RIGHT_SIDE_CHEST, {[]{return true;}}),
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_ICE_ARROWS_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 3);}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, {[]{return true;}}),
LocationAccess(RC_GERUDO_TRAINING_GROUND_MQ_ICE_ARROWS_CHEST, {[]{return SmallKeys(RR_GERUDO_TRAINING_GROUNDS, 3);}}),
}, {
//Exits
Entrance(GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER, {[]{return IsAdult && (CanUse(LONGSHOT) || (CanUse(HOOKSHOT) && Bow));}}),
Entrance(GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE, {[]{return IsAdult && CanUse(HOOKSHOT);}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER, {[]{return IsAdult && (CanUse(RG_LONGSHOT) || (CanUse(RG_HOOKSHOT) && Bow));}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE, {[]{return IsAdult && CanUse(RG_HOOKSHOT);}}),
});
}
}

View File

@@ -6,204 +6,204 @@ using namespace Logic;
using namespace Settings;
void AreaTable_Init_GerudoValley() {
areaTable[GERUDO_VALLEY] = Area("Gerudo Valley", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
areaTable[RR_GERUDO_VALLEY] = Area("Gerudo Valley", "Gerudo Valley", RHT_GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&BugRock, {[]{return BugRock || IsChild;}}),
}, {
//Locations
LocationAccess(GV_GS_SMALL_BRIDGE, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_GV_GS_SMALL_BRIDGE, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(GV_UPPER_STREAM, {[]{return true;}}),
Entrance(GV_CRATE_LEDGE, {[]{return IsChild || CanUse(LONGSHOT);}}),
Entrance(GV_GROTTO_LEDGE, {[]{return true;}}),
Entrance(GV_FORTRESS_SIDE, {[]{return (IsAdult && (CanRideEpona || CanUse(LONGSHOT) || GerudoFortress.Is(GERUDOFORTRESS_OPEN) || CarpenterRescue)) || (IsChild && CanUse(HOOKSHOT));}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_GV_UPPER_STREAM, {[]{return true;}}),
Entrance(RR_GV_CRATE_LEDGE, {[]{return IsChild || CanUse(RG_LONGSHOT);}}),
Entrance(RR_GV_GROTTO_LEDGE, {[]{return true;}}),
Entrance(RR_GV_FORTRESS_SIDE, {[]{return (IsAdult && (CanRideEpona || CanUse(RG_LONGSHOT) || GerudoFortress.Is(GERUDOFORTRESS_OPEN) || CarpenterRescue)) || (IsChild && CanUse(RG_HOOKSHOT));}}),
});
areaTable[GV_UPPER_STREAM] = Area("GV Upper Stream", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
areaTable[RR_GV_UPPER_STREAM] = Area("GV Upper Stream", "Gerudo Valley", RHT_GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(GV_UPPER_STREAM) && CanPlay(SongOfStorms));}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_GV_UPPER_STREAM) && CanPlay(SongOfStorms));}}),
}, {
//Locations
LocationAccess(GV_WATERFALL_FREESTANDING_POH, {[]{return true;}}),
LocationAccess(GV_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(GV_COW, {[]{return IsChild && CanPlay(EponasSong);}}),
LocationAccess(GV_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_GV_WATERFALL_FREESTANDING_POH, {[]{return true;}}),
LocationAccess(RC_GV_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(RC_GV_COW, {[]{return IsChild && CanPlay(EponasSong);}}),
LocationAccess(RC_GV_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(GV_LOWER_STREAM, {[]{return true;}}),
Entrance(RR_GV_LOWER_STREAM, {[]{return true;}}),
});
areaTable[GV_LOWER_STREAM] = Area("GV Lower Stream", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_GV_LOWER_STREAM] = Area("GV Lower Stream", "Gerudo Valley", RHT_GERUDO_VALLEY, DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(LAKE_HYLIA, {[]{return true;}}),
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
});
areaTable[GV_GROTTO_LEDGE] = Area("GV Grotto Ledge", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_GV_GROTTO_LEDGE] = Area("GV Grotto Ledge", "Gerudo Valley", RHT_GERUDO_VALLEY, DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GV_LOWER_STREAM, {[]{return true;}}),
Entrance(GV_OCTOROK_GROTTO, {[]{return CanUse(SILVER_GAUNTLETS);}}),
Entrance(GV_CRATE_LEDGE, {[]{return CanUse(LONGSHOT);}}),
Entrance(RR_GV_LOWER_STREAM, {[]{return true;}}),
Entrance(RR_GV_OCTOROK_GROTTO, {[]{return CanUse(RG_SILVER_GAUNTLETS);}}),
Entrance(RR_GV_CRATE_LEDGE, {[]{return CanUse(RG_LONGSHOT);}}),
});
areaTable[GV_CRATE_LEDGE] = Area("GV Crate Ledge", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GV_CRATE_LEDGE] = Area("GV Crate Ledge", "Gerudo Valley", RHT_GERUDO_VALLEY, DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GV_CRATE_FREESTANDING_POH, {[]{return true;}}),
LocationAccess(RC_GV_CRATE_FREESTANDING_POH, {[]{return true;}}),
}, {
//Exits
Entrance(GV_LOWER_STREAM, {[]{return true;}}),
Entrance(RR_GV_LOWER_STREAM, {[]{return true;}}),
});
areaTable[GV_FORTRESS_SIDE] = Area("GV Fortress Side", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
areaTable[RR_GV_FORTRESS_SIDE] = Area("GV Fortress Side", "Gerudo Valley", RHT_GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&BrokenSwordAccess, {[]{return IsAdult && (PoachersSawAccess || PoachersSaw);}}),
}, {
//Locations
LocationAccess(GV_CHEST, {[]{return IsAdult && CanUse(MEGATON_HAMMER);}}),
LocationAccess(GV_TRADE_SAW, {[]{return IsAdult && PoachersSaw;}}),
LocationAccess(GV_GS_BEHIND_TENT, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(GV_GS_PILLAR, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_GV_CHEST, {[]{return IsAdult && CanUse(RG_MEGATON_HAMMER);}}),
LocationAccess(RC_GV_TRADE_SAW, {[]{return IsAdult && PoachersSaw;}}),
LocationAccess(RC_GV_GS_BEHIND_TENT, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_GV_GS_PILLAR, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
}, {
//Exits
Entrance(GERUDO_FORTRESS, {[]{return true;}}),
Entrance(GV_UPPER_STREAM, {[]{return true;}}),
Entrance(GERUDO_VALLEY, {[]{return IsChild || CanRideEpona || CanUse(LONGSHOT) || GerudoFortress.Is(GERUDOFORTRESS_OPEN) || CarpenterRescue;}}),
Entrance(GV_CARPENTER_TENT, {[]{return IsAdult;}}),
Entrance(GV_STORMS_GROTTO, {[]{return IsAdult && CanOpenStormGrotto;}}),
Entrance(GV_CRATE_LEDGE, {[]{return false;}}),
Entrance(RR_GERUDO_FORTRESS, {[]{return true;}}),
Entrance(RR_GV_UPPER_STREAM, {[]{return true;}}),
Entrance(RR_GERUDO_VALLEY, {[]{return IsChild || CanRideEpona || CanUse(RG_LONGSHOT) || GerudoFortress.Is(GERUDOFORTRESS_OPEN) || CarpenterRescue;}}),
Entrance(RR_GV_CARPENTER_TENT, {[]{return IsAdult;}}),
Entrance(RR_GV_STORMS_GROTTO, {[]{return IsAdult && CanOpenStormGrotto;}}),
Entrance(RR_GV_CRATE_LEDGE, {[]{return false;}}),
});
areaTable[GV_CARPENTER_TENT] = Area("GV Carpenter Tent", "GV Carpenter Tent", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_GV_CARPENTER_TENT] = Area("GV Carpenter Tent", "GV Carpenter Tent", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GV_FORTRESS_SIDE, {[]{return true;}}),
Entrance(RR_GV_FORTRESS_SIDE, {[]{return true;}}),
});
areaTable[GV_OCTOROK_GROTTO] = Area("GV Octorok Grotto", "GV Octorok Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_GV_OCTOROK_GROTTO] = Area("GV Octorok Grotto", "GV Octorok Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GV_GROTTO_LEDGE, {[]{return true;}}),
Entrance(RR_GV_GROTTO_LEDGE, {[]{return true;}}),
});
areaTable[GV_STORMS_GROTTO] = Area("GV Storms Grotto", "GV Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GV_STORMS_GROTTO] = Area("GV Storms Grotto", "GV Storms Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GV_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(GV_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
LocationAccess(RC_GV_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(RC_GV_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(GV_FORTRESS_SIDE, {[]{return true;}}),
Entrance(RR_GV_FORTRESS_SIDE, {[]{return true;}}),
});
areaTable[GERUDO_FORTRESS] = Area("Gerudo Fortress", "Gerudo Fortress", GERUDO_FORTRESS, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GERUDO_FORTRESS] = Area("Gerudo Fortress", "Gerudo Fortress", RHT_GERUDO_FORTRESS, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&CarpenterRescue, {[]{return CanFinishGerudoFortress;}}),
EventAccess(&GF_GateOpen, {[]{return IsAdult && GerudoToken;}}),
EventAccess(&GtG_GateOpen, {[]{return GtG_GateOpen || (IsAdult && GerudoToken);}}),
}, {
//Locations
LocationAccess(GF_CHEST, {[]{return CanUse(HOVER_BOOTS) || (IsAdult && CanUse(SCARECROW)) || CanUse(LONGSHOT);}}),
LocationAccess(GF_HBA_1000_POINTS, {[]{return GerudoToken && CanRideEpona && Bow && AtDay;}}),
LocationAccess(GF_HBA_1500_POINTS, {[]{return GerudoToken && CanRideEpona && Bow && AtDay;}}),
LocationAccess(GF_NORTH_F1_CARPENTER, {[]{return IsAdult || KokiriSword || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);}}),
LocationAccess(GF_NORTH_F2_CARPENTER, {[]{return (IsAdult || KokiriSword || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen);}}),
LocationAccess(GF_SOUTH_F1_CARPENTER, {[]{return IsAdult || KokiriSword || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);}}),
LocationAccess(GF_SOUTH_F2_CARPENTER, {[]{return IsAdult || KokiriSword || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);}}),
LocationAccess(GF_GERUDO_MEMBERSHIP_CARD, {[]{return CanFinishGerudoFortress;}}),
LocationAccess(GF_GS_ARCHERY_RANGE, {[]{return IsAdult && HookshotOrBoomerang && GerudoToken && AtNight && CanGetNightTimeGS;}}),
LocationAccess(GF_GS_TOP_FLOOR, {[]{return IsAdult && AtNight && (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen || LogicGFJump) && CanGetNightTimeGS;}}),
LocationAccess(RC_GF_CHEST, {[]{return CanUse(RG_HOVER_BOOTS) || (IsAdult && CanUse(RG_SCARECROW)) || CanUse(RG_LONGSHOT);}}),
LocationAccess(RC_GF_HBA_1000_POINTS, {[]{return GerudoToken && CanRideEpona && Bow && AtDay;}}),
LocationAccess(RC_GF_HBA_1500_POINTS, {[]{return GerudoToken && CanRideEpona && Bow && AtDay;}}),
LocationAccess(RC_GF_NORTH_F1_CARPENTER, {[]{return IsAdult || KokiriSword || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
LocationAccess(RC_GF_NORTH_F2_CARPENTER, {[]{return (IsAdult || KokiriSword || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || LogicGerudoKitchen);}}),
LocationAccess(RC_GF_SOUTH_F1_CARPENTER, {[]{return IsAdult || KokiriSword || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
LocationAccess(RC_GF_SOUTH_F2_CARPENTER, {[]{return IsAdult || KokiriSword || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
LocationAccess(RC_GF_GERUDO_MEMBERSHIP_CARD, {[]{return CanFinishGerudoFortress;}}),
LocationAccess(RC_GF_GS_ARCHERY_RANGE, {[]{return IsAdult && HookshotOrBoomerang && GerudoToken && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_GF_GS_TOP_FLOOR, {[]{return IsAdult && AtNight && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || LogicGerudoKitchen || LogicGFJump) && CanGetNightTimeGS;}}),
}, {
//Exits
Entrance(GV_FORTRESS_SIDE, {[]{return true;}}),
Entrance(GF_OUTSIDE_GATE, {[]{return GF_GateOpen;}}),
Entrance(GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return GtG_GateOpen && (IsAdult || ShuffleDungeonEntrances);}}),
Entrance(GF_STORMS_GROTTO, {[]{return IsAdult && CanOpenStormGrotto;}}),
Entrance(RR_GV_FORTRESS_SIDE, {[]{return true;}}),
Entrance(RR_GF_OUTSIDE_GATE, {[]{return GF_GateOpen;}}),
Entrance(RR_GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return GtG_GateOpen && (IsAdult || ShuffleDungeonEntrances);}}),
Entrance(RR_GF_STORMS_GROTTO, {[]{return IsAdult && CanOpenStormGrotto;}}),
});
areaTable[GF_OUTSIDE_GATE] = Area("GF Outside Gate", "Gerudo Fortress", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GF_OUTSIDE_GATE] = Area("GF Outside Gate", "Gerudo Fortress", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GF_GateOpen, {[]{return IsAdult && GerudoToken && (ShuffleGerudoToken || ShuffleOverworldEntrances /*|| ShuffleSpecialIndoorEntrances*/);}}),
}, {}, {
//Exits
Entrance(GERUDO_FORTRESS, {[]{return (IsAdult && (Hookshot || !ShuffleOverworldEntrances)) || GF_GateOpen;}}),
Entrance(WASTELAND_NEAR_FORTRESS, {[]{return true;}}),
Entrance(RR_GERUDO_FORTRESS, {[]{return (IsAdult && (Hookshot || !ShuffleOverworldEntrances)) || GF_GateOpen;}}),
Entrance(RR_WASTELAND_NEAR_FORTRESS, {[]{return true;}}),
});
areaTable[GF_STORMS_GROTTO] = Area("GF Storms Grotto", "GF Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GF_STORMS_GROTTO] = Area("GF Storms Grotto", "GF Storms Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FreeFairies, {[]{return true;}}),
}, {}, {
//Exits
Entrance(GERUDO_FORTRESS, {[]{return true;}}),
Entrance(RR_GERUDO_FORTRESS, {[]{return true;}}),
});
areaTable[WASTELAND_NEAR_FORTRESS] = Area("Wasteland Near Fortress", "Haunted Wasteland", HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WASTELAND_NEAR_FORTRESS] = Area("Wasteland Near Fortress", "Haunted Wasteland", RHT_HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(GF_OUTSIDE_GATE, {[]{return true;}}),
Entrance(HAUNTED_WASTELAND, {[]{return CanUse(HOVER_BOOTS) || CanUse(LONGSHOT) || LogicWastelandCrossing;}}),
Entrance(RR_GF_OUTSIDE_GATE, {[]{return true;}}),
Entrance(RR_HAUNTED_WASTELAND, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT) || LogicWastelandCrossing;}}),
});
areaTable[HAUNTED_WASTELAND] = Area("Haunted Wasteland", "Haunted Wasteland", HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_HAUNTED_WASTELAND] = Area("Haunted Wasteland", "Haunted Wasteland", RHT_HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
EventAccess(&NutPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(WASTELAND_CHEST, {[]{return HasFireSource;}}),
LocationAccess(WASTELAND_BOMBCHU_SALESMAN, {[]{return AdultsWallet && (IsAdult || Sticks || KokiriSword);}}),
LocationAccess(WASTELAND_GS, {[]{return HookshotOrBoomerang;}}),
LocationAccess(RC_WASTELAND_CHEST, {[]{return HasFireSource;}}),
LocationAccess(RC_WASTELAND_BOMBCHU_SALESMAN, {[]{return AdultsWallet && (IsAdult || Sticks || KokiriSword);}}),
LocationAccess(RC_WASTELAND_GS, {[]{return HookshotOrBoomerang;}}),
}, {
//Exits
Entrance(WASTELAND_NEAR_COLOSSUS, {[]{return LogicLensWasteland || CanUse(LENS_OF_TRUTH);}}),
Entrance(WASTELAND_NEAR_FORTRESS, {[]{return CanUse(HOVER_BOOTS) || CanUse(LONGSHOT) || LogicWastelandCrossing;}}),
Entrance(RR_WASTELAND_NEAR_COLOSSUS, {[]{return LogicLensWasteland || CanUse(RG_LENS_OF_TRUTH);}}),
Entrance(RR_WASTELAND_NEAR_FORTRESS, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT) || LogicWastelandCrossing;}}),
});
areaTable[WASTELAND_NEAR_COLOSSUS] = Area("Wasteland Near Colossus", "Haunted Wasteland", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WASTELAND_NEAR_COLOSSUS] = Area("Wasteland Near Colossus", "Haunted Wasteland", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
Entrance(HAUNTED_WASTELAND, {[]{return LogicReverseWasteland || false;}}),
Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}),
Entrance(RR_HAUNTED_WASTELAND, {[]{return LogicReverseWasteland || false;}}),
});
areaTable[DESERT_COLOSSUS] = Area("Desert Colossus", "Desert Colossus", DESERT_COLOSSUS, DAY_NIGHT_CYCLE, {
areaTable[RR_DESERT_COLOSSUS] = Area("Desert Colossus", "Desert Colossus", RHT_DESERT_COLOSSUS, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPond, {[]{return FairyPond || CanPlay(SongOfStorms);}}),
EventAccess(&BugRock, {[]{return true;}}),
}, {
//Locations
LocationAccess(COLOSSUS_FREESTANDING_POH, {[]{return IsAdult && CanPlantBean(DESERT_COLOSSUS);}}),
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;}}),
LocationAccess(COLOSSUS_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_COLOSSUS_FREESTANDING_POH, {[]{return IsAdult && CanPlantBean(RR_DESERT_COLOSSUS);}}),
LocationAccess(RC_COLOSSUS_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(RC_COLOSSUS_GS_TREE, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_COLOSSUS_GS_HILL, {[]{return IsAdult && AtNight && (CanPlantBean(RR_DESERT_COLOSSUS) || CanUse(RG_LONGSHOT) || (LogicColossusGS && CanUse(RG_HOOKSHOT))) && CanGetNightTimeGS;}}),
LocationAccess(RC_COLOSSUS_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(COLOSSUS_GREAT_FAIRY_FOUNTAIN, {[]{return HasExplosives;}}),
Entrance(SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(WASTELAND_NEAR_COLOSSUS, {[]{return true;}}),
Entrance(COLOSSUS_GROTTO, {[]{return CanUse(SILVER_GAUNTLETS);}}),
Entrance(RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, {[]{return HasExplosives;}}),
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_WASTELAND_NEAR_COLOSSUS, {[]{return true;}}),
Entrance(RR_COLOSSUS_GROTTO, {[]{return CanUse(RG_SILVER_GAUNTLETS);}}),
});
areaTable[DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY] = Area("Desert Colossus From Spirit Entryway", "Desert Colossus", DESERT_COLOSSUS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY] = Area("Desert Colossus From Spirit Entryway", "Desert Colossus", RHT_DESERT_COLOSSUS, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHEIK_AT_COLOSSUS, {[]{return true;}}),
LocationAccess(RC_SHEIK_AT_COLOSSUS, {[]{return true;}}),
}, {
//Exist
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}),
});
areaTable[COLOSSUS_GREAT_FAIRY_FOUNTAIN] = Area("Colossus Great Fairy Fountain", "Colossus Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN] = Area("Colossus Great Fairy Fountain", "Colossus Great Fairy Fountain", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(COLOSSUS_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_COLOSSUS_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
}, {
//Exits
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}),
});
areaTable[COLOSSUS_GROTTO] = Area("Colossus Grotto", "Colossus Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_COLOSSUS_GROTTO] = Area("Colossus Grotto", "Colossus Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
LocationAccess(RC_COLOSSUS_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
Entrance(RR_DESERT_COLOSSUS, {[]{return true;}}),
});
}

View File

@@ -6,229 +6,229 @@ using namespace Logic;
using namespace Settings;
void AreaTable_Init_HyruleField() {
areaTable[HYRULE_FIELD] = Area("Hyrule Field", "Hyrule Field", HYRULE_FIELD, DAY_NIGHT_CYCLE, {
areaTable[RR_HYRULE_FIELD] = Area("Hyrule Field", "Hyrule Field", RHT_HYRULE_FIELD, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&BigPoeKill, {[]{return CanUse(BOW) && CanRideEpona && HasBottle;}}),
EventAccess(&BigPoeKill, {[]{return CanUse(RG_FAIRY_BOW) && CanRideEpona && HasBottle;}}),
}, {
//Locations
LocationAccess(HF_OCARINA_OF_TIME_ITEM, {[]{return IsChild && HasAllStones;}}),
LocationAccess(SONG_FROM_OCARINA_OF_TIME, {[]{return IsChild && HasAllStones;}}),
LocationAccess(RC_HF_OCARINA_OF_TIME_ITEM, {[]{return IsChild && HasAllStones;}}),
LocationAccess(RC_SONG_FROM_OCARINA_OF_TIME, {[]{return IsChild && HasAllStones;}}),
}, {
//Exits
Entrance(LW_BRIDGE, {[]{return true;}}),
Entrance(LAKE_HYLIA, {[]{return true;}}),
Entrance(GERUDO_VALLEY, {[]{return true;}}),
Entrance(MARKET_ENTRANCE, {[]{return true;}}),
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(ZR_FRONT, {[]{return true;}}),
Entrance(LON_LON_RANCH, {[]{return true;}}),
Entrance(HF_SOUTHEAST_GROTTO, {[]{return Here(HYRULE_FIELD, []{return CanBlastOrSmash;});}}),
Entrance(HF_OPEN_GROTTO, {[]{return true;}}),
Entrance(HF_INSIDE_FENCE_GROTTO, {[]{return CanOpenBombGrotto;}}),
Entrance(HF_COW_GROTTO, {[]{return (CanUse(MEGATON_HAMMER) || IsChild) && CanOpenBombGrotto;}}),
Entrance(HF_NEAR_MARKET_GROTTO, {[]{return Here(HYRULE_FIELD, []{return CanBlastOrSmash;});}}),
Entrance(HF_FAIRY_GROTTO, {[]{return Here(HYRULE_FIELD, []{return CanBlastOrSmash;});}}),
Entrance(HF_NEAR_KAK_GROTTO, {[]{return CanOpenBombGrotto;}}),
Entrance(HF_TEKTITE_GROTTO, {[]{return CanOpenBombGrotto;}}),
Entrance(RR_LW_BRIDGE, {[]{return true;}}),
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
Entrance(RR_GERUDO_VALLEY, {[]{return true;}}),
Entrance(RR_MARKET_ENTRANCE, {[]{return true;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_ZR_FRONT, {[]{return true;}}),
Entrance(RR_LON_LON_RANCH, {[]{return true;}}),
Entrance(RR_HF_SOUTHEAST_GROTTO, {[]{return Here(RR_HYRULE_FIELD, []{return CanBlastOrSmash;});}}),
Entrance(RR_HF_OPEN_GROTTO, {[]{return true;}}),
Entrance(RR_HF_INSIDE_FENCE_GROTTO, {[]{return CanOpenBombGrotto;}}),
Entrance(RR_HF_COW_GROTTO, {[]{return (CanUse(RG_MEGATON_HAMMER) || IsChild) && CanOpenBombGrotto;}}),
Entrance(RR_HF_NEAR_MARKET_GROTTO, {[]{return Here(RR_HYRULE_FIELD, []{return CanBlastOrSmash;});}}),
Entrance(RR_HF_FAIRY_GROTTO, {[]{return Here(RR_HYRULE_FIELD, []{return CanBlastOrSmash;});}}),
Entrance(RR_HF_NEAR_KAK_GROTTO, {[]{return CanOpenBombGrotto;}}),
Entrance(RR_HF_TEKTITE_GROTTO, {[]{return CanOpenBombGrotto;}}),
});
areaTable[HF_SOUTHEAST_GROTTO] = Area("HF Southeast Grotto", "HF Southeast Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[RR_HF_SOUTHEAST_GROTTO] = Area("HF Southeast Grotto", "HF Southeast Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(HF_SOUTHEAST_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(HF_SOUTHEAST_GROTTO_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_HF_SOUTHEAST_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(RC_HF_SOUTHEAST_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_OPEN_GROTTO] = Area("HF Open Grotto", "HF Open Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[RR_HF_OPEN_GROTTO] = Area("HF Open Grotto", "HF Open Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(HF_OPEN_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(HF_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_HF_OPEN_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(RC_HF_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_INSIDE_FENCE_GROTTO] = Area("HF Inside Fence Grotto", "HF Inside Fence Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_HF_INSIDE_FENCE_GROTTO] = Area("HF Inside Fence Grotto", "HF Inside Fence Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(HF_DEKU_SCRUB_GROTTO, {[]{return CanStunDeku;}}),
LocationAccess(RC_HF_DEKU_SCRUB_GROTTO, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_COW_GROTTO] = Area("HF Cow Grotto", "HF Cow Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[RR_HF_COW_GROTTO] = Area("HF Cow Grotto", "HF Cow Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(HF_GS_COW_GROTTO, {[]{return HasFireSource && HookshotOrBoomerang;}}),
LocationAccess(HF_COW_GROTTO_COW, {[]{return HasFireSource && CanPlay(EponasSong);}}),
LocationAccess(HF_COW_GROTTO_GOSSIP_STONE, {[]{return HasFireSource;}}),
LocationAccess(RC_HF_GS_COW_GROTTO, {[]{return HasFireSource && HookshotOrBoomerang;}}),
LocationAccess(RC_HF_COW_GROTTO_COW, {[]{return HasFireSource && CanPlay(EponasSong);}}),
LocationAccess(RC_HF_COW_GROTTO_GOSSIP_STONE, {[]{return HasFireSource;}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_NEAR_MARKET_GROTTO] = Area("HF Near Market Grotto", "HF Near Market Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[RR_HF_NEAR_MARKET_GROTTO] = Area("HF Near Market Grotto", "HF Near Market Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(HF_NEAR_MARKET_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_HF_NEAR_MARKET_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(RC_HF_NEAR_MARKET_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_FAIRY_GROTTO] = Area("HF Fairy Grotto", "HF Fairy Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_HF_FAIRY_GROTTO] = Area("HF Fairy Grotto", "HF Fairy Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FreeFairies, {[]{return true;}}),
}, {}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_NEAR_KAK_GROTTO] = Area("HF Near Kak Grotto", "HF Near Kak Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_HF_NEAR_KAK_GROTTO] = Area("HF Near Kak Grotto", "HF Near Kak Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(HF_GS_NEAR_KAK_GROTTO, {[]{return HookshotOrBoomerang;}}),
LocationAccess(RC_HF_GS_NEAR_KAK_GROTTO, {[]{return HookshotOrBoomerang;}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
});
areaTable[HF_TEKTITE_GROTTO] = Area("HF Tektite Grotto", "HF Tektite Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_HF_TEKTITE_GROTTO] = Area("HF Tektite Grotto", "HF Tektite Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(HF_TEKTITE_GROTTO_FREESTANDING_POH, {[]{return ProgressiveScale >= 2 || CanUse(IRON_BOOTS);}}),
LocationAccess(RC_HF_TEKTITE_GROTTO_FREESTANDING_POH, {[]{return ProgressiveScale >= 2 || CanUse(RG_IRON_BOOTS);}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
});
areaTable[LAKE_HYLIA] = Area("Lake Hylia", "Lake Hylia", LAKE_HYLIA, DAY_NIGHT_CYCLE, {
areaTable[RR_LAKE_HYLIA] = Area("Lake Hylia", "Lake Hylia", RHT_LAKE_HYLIA, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(LAKE_HYLIA) && CanPlay(SongOfStorms));}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(STICKS);}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_LAKE_HYLIA) && CanPlay(SongOfStorms));}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(RG_STICKS);}}),
EventAccess(&BugShrub, {[]{return BugShrub || (IsChild && CanCutShrubs);}}),
EventAccess(&ChildScarecrow, {[]{return ChildScarecrow || (IsChild && Ocarina);}}),
EventAccess(&AdultScarecrow, {[]{return AdultScarecrow || (IsAdult && Ocarina);}}),
}, {
//Locations
LocationAccess(LH_UNDERWATER_ITEM, {[]{return IsChild && CanDive;}}),
LocationAccess(LH_SUN, {[]{return IsAdult && WaterTempleClear && CanUse(BOW);}}),
LocationAccess(LH_FREESTANDING_POH, {[]{return IsAdult && (CanUse(SCARECROW) || CanPlantBean(LAKE_HYLIA));}}),
LocationAccess(LH_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(LH_GS_LAB_WALL, {[]{return IsChild && (HookshotOrBoomerang || (LogicLabWallGS && (Sticks || KokiriSword || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)))) && AtNight && CanGetNightTimeGS;}}),
LocationAccess(LH_GS_SMALL_ISLAND, {[]{return IsChild && CanChildAttack && AtNight && CanGetNightTimeGS;}}),
LocationAccess(LH_GS_TREE, {[]{return IsAdult && CanUse(LONGSHOT) && AtNight && CanGetNightTimeGS;}}),
LocationAccess(LH_LAB_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(LH_GOSSIP_STONE_SOUTHEAST, {[]{return true;}}),
LocationAccess(LH_GOSSIP_STONE_SOUTHWEST, {[]{return true;}}),
LocationAccess(RC_LH_UNDERWATER_ITEM, {[]{return IsChild && CanDive;}}),
LocationAccess(RC_LH_SUN, {[]{return IsAdult && WaterTempleClear && CanUse(RG_FAIRY_BOW);}}),
LocationAccess(RC_LH_FREESTANDING_POH, {[]{return IsAdult && (CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA));}}),
LocationAccess(RC_LH_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(RC_LH_GS_LAB_WALL, {[]{return IsChild && (HookshotOrBoomerang || (LogicLabWallGS && (Sticks || KokiriSword || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)))) && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_LH_GS_SMALL_ISLAND, {[]{return IsChild && CanChildAttack && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_LH_GS_TREE, {[]{return IsAdult && CanUse(RG_LONGSHOT) && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_LH_LAB_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_LH_SOUTHEAST_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_LH_SOUTHWEST_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(ZORAS_DOMAIN, {[]{return IsChild && (CanDive || CanUse(IRON_BOOTS));}}),
Entrance(LH_OWL_FLIGHT, {[]{return IsChild;}}),
Entrance(LH_FISHING_ISLAND, {[]{return IsChild || CanUse(SCARECROW) || CanPlantBean(LAKE_HYLIA) || WaterTempleClear;}}),
Entrance(LH_LAB, {[]{return true;}}),
Entrance(WATER_TEMPLE_ENTRYWAY, {[]{return CanUse(HOOKSHOT) && ((CanUse(IRON_BOOTS) || (LogicWaterHookshotEntry && ProgressiveScale >= 2)) || (IsAdult && CanUse(LONGSHOT) && ProgressiveScale >= 2));}}),
Entrance(LH_GROTTO, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_ZORAS_DOMAIN, {[]{return IsChild && (CanDive || CanUse(RG_IRON_BOOTS));}}),
Entrance(RR_LH_OWL_FLIGHT, {[]{return IsChild;}}),
Entrance(RR_LH_FISHING_ISLAND, {[]{return IsChild || CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA) || WaterTempleClear;}}),
Entrance(RR_LH_LAB, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_HOOKSHOT) && ((CanUse(RG_IRON_BOOTS) || (LogicWaterHookshotEntry && ProgressiveScale >= 2)) || (IsAdult && CanUse(RG_LONGSHOT) && ProgressiveScale >= 2));}}),
Entrance(RR_LH_GROTTO, {[]{return true;}}),
});
areaTable[LH_FISHING_ISLAND] = Area("LH Fishing Island", "Lake Hylia", LAKE_HYLIA, DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_LH_FISHING_ISLAND] = Area("LH Fishing Island", "Lake Hylia", RHT_LAKE_HYLIA, DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(LAKE_HYLIA, {[]{return true;}}),
Entrance(LH_FISHING_HOLE, {[]{return true;}}),
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
Entrance(RR_LH_FISHING_HOLE, {[]{return true;}}),
});
areaTable[LH_OWL_FLIGHT] = Area("LH Owl Flight", "Lake Hylia", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_LH_OWL_FLIGHT] = Area("LH Owl Flight", "Lake Hylia", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
});
areaTable[LH_LAB] = Area("LH Lab", "LH Lab", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_LH_LAB] = Area("LH Lab", "LH Lab", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&EyedropsAccess, {[]{return EyedropsAccess || (IsAdult && (EyeballFrogAccess || (EyeballFrog && DisableTradeRevert)));}}),
}, {
//Locations
LocationAccess(LH_LAB_DIVE, {[]{return ProgressiveScale >= 2 || (LogicLabDiving && CanUse(IRON_BOOTS) && CanUse(HOOKSHOT));}}),
LocationAccess(LH_TRADE_FROG, {[]{return IsAdult && EyeballFrog;}}),
LocationAccess(LH_GS_LAB_CRATE, {[]{return CanUse(IRON_BOOTS) && CanUse(HOOKSHOT);}}),
LocationAccess(RC_LH_LAB_DIVE, {[]{return ProgressiveScale >= 2 || (LogicLabDiving && CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT));}}),
LocationAccess(RC_LH_TRADE_FROG, {[]{return IsAdult && EyeballFrog;}}),
LocationAccess(RC_LH_GS_LAB_CRATE, {[]{return CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT);}}),
}, {
//Exits
Entrance(LAKE_HYLIA, {[]{return true;}}),
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
});
areaTable[LH_FISHING_HOLE] = Area("LH Fishing Hole", "LH Fishing Hole", NONE, DAY_NIGHT_CYCLE, {}, {
areaTable[RR_LH_FISHING_HOLE] = Area("LH Fishing Hole", "LH Fishing Hole", RHT_NONE, DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LH_CHILD_FISHING, {[]{return IsChild;}}),
LocationAccess(LH_ADULT_FISHING, {[]{return IsAdult;}}),
LocationAccess(RC_LH_CHILD_FISHING, {[]{return IsChild;}}),
LocationAccess(RC_LH_ADULT_FISHING, {[]{return IsAdult;}}),
}, {
//Exits
Entrance(LH_FISHING_ISLAND, {[]{return true;}}),
Entrance(RR_LH_FISHING_ISLAND, {[]{return true;}}),
});
areaTable[LH_GROTTO] = Area("LH Grotto", "LH Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_LH_GROTTO] = Area("LH Grotto", "LH Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LH_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(LH_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(LH_DEKU_SCRUB_GROTTO_CENTER, {[]{return CanStunDeku;}}),
LocationAccess(RC_LH_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(RC_LH_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(RC_LH_DEKU_SCRUB_GROTTO_CENTER, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(LAKE_HYLIA, {[]{return true;}}),
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
});
areaTable[LON_LON_RANCH] = Area("Lon Lon Ranch", "Lon Lon Ranch", LON_LON_RANCH, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_LON_LON_RANCH] = Area("Lon Lon Ranch", "Lon Lon Ranch", RHT_LON_LON_RANCH, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&Epona, {[]{return Epona || (CanPlay(EponasSong) && IsAdult && AtDay);}}),
EventAccess(&LinksCow, {[]{return LinksCow || (CanPlay(EponasSong) && IsAdult && AtDay);}}),
}, {
//Locations
LocationAccess(SONG_FROM_MALON, {[]{return IsChild && ZeldasLetter && Ocarina && AtDay;}}),
LocationAccess(LLR_GS_TREE, {[]{return IsChild;}}),
LocationAccess(LLR_GS_RAIN_SHED, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(LLR_GS_HOUSE_WINDOW, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(LLR_GS_BACK_WALL, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_SONG_FROM_MALON, {[]{return IsChild && ZeldasLetter && Ocarina && AtDay;}}),
LocationAccess(RC_LLR_GS_TREE, {[]{return IsChild;}}),
LocationAccess(RC_LLR_GS_RAIN_SHED, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_LLR_GS_HOUSE_WINDOW, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_LLR_GS_BACK_WALL, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(LLR_TALONS_HOUSE, {[]{return true;}}),
Entrance(LLR_STABLES, {[]{return true;}}),
Entrance(LLR_TOWER, {[]{return true;}}),
Entrance(LLR_GROTTO, {[]{return IsChild;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_LLR_TALONS_HOUSE, {[]{return true;}}),
Entrance(RR_LLR_STABLES, {[]{return true;}}),
Entrance(RR_LLR_TOWER, {[]{return true;}}),
Entrance(RR_LLR_GROTTO, {[]{return IsChild;}}),
});
areaTable[LLR_TALONS_HOUSE] = Area("LLR Talons House", "LLR Talons House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_LLR_TALONS_HOUSE] = Area("LLR Talons House", "LLR Talons House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LLR_TALONS_CHICKENS, {[]{return IsChild && AtDay && ZeldasLetter;}}),
LocationAccess(RC_LLR_TALONS_CHICKENS, {[]{return IsChild && AtDay && ZeldasLetter;}}),
}, {
//Exits
Entrance(LON_LON_RANCH, {[]{return true;}}),
Entrance(RR_LON_LON_RANCH, {[]{return true;}}),
});
areaTable[LLR_STABLES] = Area("LLR Stables", "LLR Stables", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_LLR_STABLES] = Area("LLR Stables", "LLR Stables", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LLR_STABLES_LEFT_COW, {[]{return CanPlay(EponasSong);}}),
LocationAccess(LLR_STABLES_RIGHT_COW, {[]{return CanPlay(EponasSong);}}),
LocationAccess(RC_LLR_STABLES_LEFT_COW, {[]{return CanPlay(EponasSong);}}),
LocationAccess(RC_LLR_STABLES_RIGHT_COW, {[]{return CanPlay(EponasSong);}}),
}, {
//Exits
Entrance(LON_LON_RANCH, {[]{return true;}}),
Entrance(RR_LON_LON_RANCH, {[]{return true;}}),
});
areaTable[LLR_TOWER] = Area("LLR Tower", "LLR Tower", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_LLR_TOWER] = Area("LLR Tower", "LLR Tower", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LLR_FREESTANDING_POH, {[]{return IsChild;}}),
LocationAccess(LLR_TOWER_LEFT_COW, {[]{return CanPlay(EponasSong);}}),
LocationAccess(LLR_TOWER_RIGHT_COW, {[]{return CanPlay(EponasSong);}}),
LocationAccess(RC_LLR_FREESTANDING_POH, {[]{return IsChild;}}),
LocationAccess(RC_LLR_TOWER_LEFT_COW, {[]{return CanPlay(EponasSong);}}),
LocationAccess(RC_LLR_TOWER_RIGHT_COW, {[]{return CanPlay(EponasSong);}}),
}, {
//Exits
Entrance(LON_LON_RANCH, {[]{return true;}}),
Entrance(RR_LON_LON_RANCH, {[]{return true;}}),
});
areaTable[LLR_GROTTO] = Area("LLR Grotto", "LLR Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_LLR_GROTTO] = Area("LLR Grotto", "LLR Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LLR_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(LLR_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(LLR_DEKU_SCRUB_GROTTO_CENTER, {[]{return CanStunDeku;}}),
LocationAccess(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
LocationAccess(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
LocationAccess(RC_LLR_DEKU_SCRUB_GROTTO_CENTER, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(LON_LON_RANCH, {[]{return true;}}),
Entrance(RR_LON_LON_RANCH, {[]{return true;}}),
});
}

View File

@@ -10,36 +10,36 @@ void AreaTable_Init_IceCavern() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[ICE_CAVERN_ENTRYWAY] = Area("Ice Cavern Entryway", "Ice Cavern", ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_ICE_CAVERN_ENTRYWAY] = Area("Ice Cavern Entryway", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(ICE_CAVERN_BEGINNING, {[]{return Dungeon::IceCavern.IsVanilla();}}),
Entrance(ICE_CAVERN_MQ_BEGINNING, {[]{return Dungeon::IceCavern.IsMQ();}}),
Entrance(ZORAS_FOUNTAIN, {[]{return true;}}),
Entrance(RR_ICE_CAVERN_BEGINNING, {[]{return Dungeon::IceCavern.IsVanilla();}}),
Entrance(RR_ICE_CAVERN_MQ_BEGINNING, {[]{return Dungeon::IceCavern.IsMQ();}}),
Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::IceCavern.IsVanilla()) {
areaTable[ICE_CAVERN_BEGINNING] = Area("Ice Cavern Beginning", "Ice Cavern", ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_ICE_CAVERN_BEGINNING] = Area("Ice Cavern Beginning", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(ICE_CAVERN_ENTRYWAY, {[]{return true;}}),
Entrance(ICE_CAVERN_MAIN, {[]{return Here(ICE_CAVERN_BEGINNING, []{return IsAdult || HasExplosives || CanUse(DINS_FIRE);});}}),
Entrance(RR_ICE_CAVERN_ENTRYWAY, {[]{return true;}}),
Entrance(RR_ICE_CAVERN_MAIN, {[]{return Here(RR_ICE_CAVERN_BEGINNING, []{return IsAdult || HasExplosives || CanUse(RG_DINS_FIRE);});}}),
});
areaTable[ICE_CAVERN_MAIN] = Area("Ice Cavern", "Ice Cavern", ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_ICE_CAVERN_MAIN] = Area("Ice Cavern", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&BlueFireAccess, {[]{return BlueFireAccess || (IsAdult && HasBottle);}}),
}, {
//Locations
LocationAccess(ICE_CAVERN_MAP_CHEST, {[]{return BlueFire && IsAdult;}}),
LocationAccess(ICE_CAVERN_COMPASS_CHEST, {[]{return BlueFire;}}),
LocationAccess(ICE_CAVERN_IRON_BOOTS_CHEST, {[]{return BlueFire && (IsAdult || Slingshot || Sticks || KokiriSword || CanUse(DINS_FIRE));}}),
LocationAccess(SHEIK_IN_ICE_CAVERN, {[]{return BlueFire && IsAdult;}}),
LocationAccess(ICE_CAVERN_FREESTANDING_POH, {[]{return BlueFire;}}),
LocationAccess(ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, {[]{return HookshotOrBoomerang;}}),
LocationAccess(ICE_CAVERN_GS_HEART_PIECE_ROOM, {[]{return BlueFire && HookshotOrBoomerang;}}),
LocationAccess(ICE_CAVERN_GS_PUSH_BLOCK_ROOM, {[]{return BlueFire && (HookshotOrBoomerang || (LogicIceBlockGS && IsAdult && CanUse(HOVER_BOOTS)));}}),
LocationAccess(RC_ICE_CAVERN_MAP_CHEST, {[]{return BlueFire && IsAdult;}}),
LocationAccess(RC_ICE_CAVERN_COMPASS_CHEST, {[]{return BlueFire;}}),
LocationAccess(RC_ICE_CAVERN_IRON_BOOTS_CHEST, {[]{return BlueFire && (IsAdult || Slingshot || Sticks || KokiriSword || CanUse(RG_DINS_FIRE));}}),
LocationAccess(RC_SHEIK_IN_ICE_CAVERN, {[]{return BlueFire && IsAdult;}}),
LocationAccess(RC_ICE_CAVERN_FREESTANDING_POH, {[]{return BlueFire;}}),
LocationAccess(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, {[]{return HookshotOrBoomerang;}}),
LocationAccess(RC_ICE_CAVERN_GS_HEART_PIECE_ROOM, {[]{return BlueFire && HookshotOrBoomerang;}}),
LocationAccess(RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM, {[]{return BlueFire && (HookshotOrBoomerang || (LogicIceBlockGS && IsAdult && CanUse(RG_HOVER_BOOTS)));}}),
}, {});
}
@@ -47,39 +47,39 @@ void AreaTable_Init_IceCavern() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::IceCavern.IsMQ()) {
areaTable[ICE_CAVERN_MQ_BEGINNING] = Area("Ice Cavern MQ Beginning", "Ice Cavern", ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_ICE_CAVERN_MQ_BEGINNING] = Area("Ice Cavern MQ Beginning", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
}, {}, {
//Exits
Entrance(ICE_CAVERN_ENTRYWAY, {[]{return true;}}),
Entrance(ICE_CAVERN_MQ_MAP_ROOM, {[]{return IsAdult || CanUse(DINS_FIRE) || (HasExplosives && (CanUse(STICKS) || CanUse(SLINGSHOT) || KokiriSword));}}),
Entrance(ICE_CAVERN_MQ_COMPASS_ROOM, {[]{return IsAdult && BlueFire;}}),
Entrance(ICE_CAVERN_MQ_IRON_BOOTS_REGION, {[]{return BlueFire;}}),
Entrance(RR_ICE_CAVERN_ENTRYWAY, {[]{return true;}}),
Entrance(RR_ICE_CAVERN_MQ_MAP_ROOM, {[]{return IsAdult || CanUse(RG_DINS_FIRE) || (HasExplosives && (CanUse(RG_STICKS) || CanUse(RG_FAIRY_SLINGSHOT) || KokiriSword));}}),
Entrance(RR_ICE_CAVERN_MQ_COMPASS_ROOM, {[]{return IsAdult && BlueFire;}}),
Entrance(RR_ICE_CAVERN_MQ_IRON_BOOTS_REGION, {[]{return BlueFire;}}),
});
areaTable[ICE_CAVERN_MQ_MAP_ROOM] = Area("Ice Cavern MQ Map Room", "Ice Cavern", ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_ICE_CAVERN_MQ_MAP_ROOM] = Area("Ice Cavern MQ Map Room", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&BlueFireAccess, {[]{return BlueFireAccess || HasBottle;}}),
}, {
//Locations
LocationAccess(ICE_CAVERN_MQ_MAP_CHEST, {[]{return BlueFire && (IsAdult || CanUse(STICKS) || KokiriSword || CanUseProjectile);}}),
LocationAccess(RC_ICE_CAVERN_MQ_MAP_CHEST, {[]{return BlueFire && (IsAdult || CanUse(RG_STICKS) || KokiriSword || CanUseProjectile);}}),
}, {});
areaTable[ICE_CAVERN_MQ_IRON_BOOTS_REGION] = Area("Ice Cavern MQ Iron Boots Region", "Ice Cavern", ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_ICE_CAVERN_MQ_IRON_BOOTS_REGION] = Area("Ice Cavern MQ Iron Boots Region", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(ICE_CAVERN_MQ_IRON_BOOTS_CHEST, {[]{return IsAdult;}}),
LocationAccess(SHEIK_IN_ICE_CAVERN, {[]{return IsAdult;}}),
LocationAccess(ICE_CAVERN_MQ_GS_ICE_BLOCK, {[]{return IsAdult || CanUseProjectile;}}),
LocationAccess(ICE_CAVERN_MQ_GS_SCARECROW, {[]{return (CanUse(SCARECROW) || (HoverBoots && CanUse(LONGSHOT)) || LogicIceMQScarecrow) && IsAdult;}}),
//Tricks: (CanUse(SCARECROW) || (HoverBoots && CanUse(LONGSHOT)) || LogicIceMQScarecrow) && IsAdult
LocationAccess(RC_ICE_CAVERN_MQ_IRON_BOOTS_CHEST, {[]{return IsAdult;}}),
LocationAccess(RC_SHEIK_IN_ICE_CAVERN, {[]{return IsAdult;}}),
LocationAccess(RC_ICE_CAVERN_MQ_GS_ICE_BLOCK, {[]{return IsAdult || CanUseProjectile;}}),
LocationAccess(RC_ICE_CAVERN_MQ_GS_SCARECROW, {[]{return (CanUse(RG_SCARECROW) || (HoverBoots && CanUse(RG_LONGSHOT)) || LogicIceMQScarecrow) && IsAdult;}}),
//Tricks: (CanUse(RG_SCARECROW) || (HoverBoots && CanUse(RG_LONGSHOT)) || LogicIceMQScarecrow) && IsAdult
}, {});
areaTable[ICE_CAVERN_MQ_COMPASS_ROOM] = Area("Ice Cavern MQ Compass Room", "Ice Cavern", ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_ICE_CAVERN_MQ_COMPASS_ROOM] = Area("Ice Cavern MQ Compass Room", "Ice Cavern", RHT_ICE_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(ICE_CAVERN_MQ_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(ICE_CAVERN_MQ_FREESTANDING_POH, {[]{return HasExplosives;}}),
LocationAccess(ICE_CAVERN_MQ_GS_RED_ICE, {[]{return CanPlay(SongOfTime) || LogicIceMQRedIceGS;}}),
LocationAccess(RC_ICE_CAVERN_MQ_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(RC_ICE_CAVERN_MQ_FREESTANDING_POH, {[]{return HasExplosives;}}),
LocationAccess(RC_ICE_CAVERN_MQ_GS_RED_ICE, {[]{return CanPlay(SongOfTime) || LogicIceMQRedIceGS;}}),
//Trick: CanPlay(SongOfTime) || LogicIceMQRedIceGS
}, {});
}

View File

@@ -10,151 +10,151 @@ void AreaTable_Init_JabuJabusBelly() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[JABU_JABUS_BELLY_ENTRYWAY] = Area("Jabu Jabus Belly Entryway", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_JABU_JABUS_BELLY_ENTRYWAY] = Area("Jabu Jabus Belly Entryway", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_BEGINNING, {[]{return Dungeon::JabuJabusBelly.IsVanilla();}}),
Entrance(JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return Dungeon::JabuJabusBelly.IsMQ();}}),
Entrance(ZORAS_FOUNTAIN, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_BEGINNING, {[]{return Dungeon::JabuJabusBelly.IsVanilla();}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return Dungeon::JabuJabusBelly.IsMQ();}}),
Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::JabuJabusBelly.IsVanilla()) {
areaTable[JABU_JABUS_BELLY_BEGINNING] = Area("Jabu Jabus Belly Beginning", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_JABU_JABUS_BELLY_BEGINNING] = Area("Jabu Jabus Belly Beginning", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return CanUseProjectile;}}),
Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return CanUseProjectile;}}),
});
areaTable[JABU_JABUS_BELLY_LIFT_MIDDLE] = Area("Jabu Jabus Belly Lift Middle", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_JABU_JABUS_BELLY_LIFT_MIDDLE] = Area("Jabu Jabus Belly Lift Middle", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_BEGINNING, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_LIFT_LOWER, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_NEAR_BOSS_ROOM, {[]{return HasAccessTo(JABU_JABUS_BELLY_LIFT_UPPER) || (LogicJabuBossHover && IsAdult && CanUse(HOVER_BOOTS));}}),
Entrance(RR_JABU_JABUS_BELLY_BEGINNING, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_LIFT_LOWER, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, {[]{return HasAccessTo(RR_JABU_JABUS_BELLY_LIFT_UPPER) || (LogicJabuBossHover && IsAdult && CanUse(RG_HOVER_BOOTS));}}),
});
areaTable[JABU_JABUS_BELLY_MAIN_UPPER] = Area("Jabu Jabus Belly Main Upper", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_JABU_JABUS_BELLY_MAIN_UPPER] = Area("Jabu Jabus Belly Main Upper", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_BIGOCTO_ROOM, {[]{return Here(JABU_JABUS_BELLY_GREEN_TENTACLE, []{return CanUse(BOOMERANG);});}}),
Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_BIGOCTO_ROOM, {[]{return Here(RR_JABU_JABUS_BELLY_GREEN_TENTACLE, []{return CanUse(RG_BOOMERANG);});}}),
});
areaTable[JABU_JABUS_BELLY_MAIN_LOWER] = Area("Jabu Jabus Belly Main Lower", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_JABU_JABUS_BELLY_MAIN_LOWER] = Area("Jabu Jabus Belly Main Lower", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, {[]{return HookshotOrBoomerang;}}),
LocationAccess(JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, {[]{return HookshotOrBoomerang;}}),
LocationAccess(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, {[]{return HookshotOrBoomerang;}}),
LocationAccess(RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, {[]{return HookshotOrBoomerang;}}),
}, {
//Exits
Entrance(JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_SHABOMB_CORRIDOR, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_LOWER_SIDE_ROOM, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_SHABOMB_CORRIDOR, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_LOWER_SIDE_ROOM, {[]{return true;}}),
});
areaTable[JABU_JABUS_BELLY_SHABOMB_CORRIDOR] = Area("Jabu Jabus Belly Shabomb Corridor", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_JABU_JABUS_BELLY_SHABOMB_CORRIDOR] = Area("Jabu Jabus Belly Shabomb Corridor", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM, {[]{return true;}}),
}, {
//Exits
Entrance(JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_LIFT_LOWER, {[]{return CanUseProjectile;}}),
Entrance(RR_JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_LIFT_LOWER, {[]{return CanUseProjectile;}}),
});
areaTable[JABU_JABUS_BELLY_LOWER_SIDE_ROOM] = Area("Jabu Jabus Belly Lower Side Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_JABU_JABUS_BELLY_LOWER_SIDE_ROOM] = Area("Jabu Jabus Belly Lower Side Room", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return FairyPot || (CanUse(BOOMERANG) || CanUse(HOVER_BOOTS));}}),
EventAccess(&FairyPot, {[]{return FairyPot || (CanUse(RG_BOOMERANG) || CanUse(RG_HOVER_BOOTS));}}),
}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}),
});
areaTable[JABU_JABUS_BELLY_LIFT_LOWER] = Area("Jabu Jabus Belly Lift Lower", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_JABU_JABUS_BELLY_LIFT_LOWER] = Area("Jabu Jabus Belly Lift Lower", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_DEKU_SCRUB, {[]{return (IsChild || CanDive || LogicJabuAlcoveJumpDive || CanUse(IRON_BOOTS)) && CanStunDeku;}}),
LocationAccess(RC_JABU_JABUS_BELLY_DEKU_SCRUB, {[]{return (IsChild || CanDive || LogicJabuAlcoveJumpDive || CanUse(RG_IRON_BOOTS)) && CanStunDeku;}}),
}, {
//Exits
Entrance(JABU_JABUS_BELLY_SHABOMB_CORRIDOR, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_SHABOMB_CORRIDOR, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
});
areaTable[JABU_JABUS_BELLY_FORKED_CORRIDOR] = Area("Jabu Jabus Belly Forked Corridor", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_JABU_JABUS_BELLY_FORKED_CORRIDOR] = Area("Jabu Jabus Belly Forked Corridor", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_BOOMERANG_ROOM, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_MAP_ROOM, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_COMPASS_ROOM, {[]{return Here(JABU_JABUS_BELLY_MAP_ROOM, []{return CanUse(BOOMERANG);});}}),
Entrance(JABU_JABUS_BELLY_BLUE_TENTACLE, {[]{return Here(JABU_JABUS_BELLY_MAP_ROOM, []{return CanUse(BOOMERANG);});}}),
Entrance(JABU_JABUS_BELLY_GREEN_TENTACLE, {[]{return Here(JABU_JABUS_BELLY_BLUE_TENTACLE, []{return CanUse(BOOMERANG);});}}),
Entrance(RR_JABU_JABUS_BELLY_MAIN_UPPER, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_BOOMERANG_ROOM, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MAP_ROOM, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_COMPASS_ROOM, {[]{return Here(RR_JABU_JABUS_BELLY_MAP_ROOM, []{return CanUse(RG_BOOMERANG);});}}),
Entrance(RR_JABU_JABUS_BELLY_BLUE_TENTACLE, {[]{return Here(RR_JABU_JABUS_BELLY_MAP_ROOM, []{return CanUse(RG_BOOMERANG);});}}),
Entrance(RR_JABU_JABUS_BELLY_GREEN_TENTACLE, {[]{return Here(RR_JABU_JABUS_BELLY_BLUE_TENTACLE, []{return CanUse(RG_BOOMERANG);});}}),
});
areaTable[JABU_JABUS_BELLY_BOOMERANG_ROOM] = Area("Jabu Jabus Belly Boomerang Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_JABU_JABUS_BELLY_BOOMERANG_ROOM] = Area("Jabu Jabus Belly Boomerang Room", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_BOOMERANG_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_BOOMERANG_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}),
});
areaTable[JABU_JABUS_BELLY_MAP_ROOM] = Area("Jabu Jabus Belly Map Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_JABU_JABUS_BELLY_MAP_ROOM] = Area("Jabu Jabus Belly Map Room", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_MAP_CHEST, {[]{return CanUse(BOOMERANG);}}),
LocationAccess(RC_JABU_JABUS_BELLY_MAP_CHEST, {[]{return CanUse(RG_BOOMERANG);}}),
}, {
//Exits
Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}),
});
areaTable[JABU_JABUS_BELLY_COMPASS_ROOM] = Area("Jabu Jabus Belly Compass Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_JABU_JABUS_BELLY_COMPASS_ROOM] = Area("Jabu Jabus Belly Compass Room", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_COMPASS_CHEST, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(RC_JABU_JABUS_BELLY_COMPASS_CHEST, {[]{return IsAdult || CanChildAttack;}}),
}, {
//Exits
Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return true;}}),
});
areaTable[JABU_JABUS_BELLY_BLUE_TENTACLE] = Area("Jabu Jabus Belly Blue Tentacle", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_JABU_JABUS_BELLY_BLUE_TENTACLE] = Area("Jabu Jabus Belly Blue Tentacle", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return Here(JABU_JABUS_BELLY_BLUE_TENTACLE, []{return CanUse(BOOMERANG);});}}),
Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return Here(RR_JABU_JABUS_BELLY_BLUE_TENTACLE, []{return CanUse(RG_BOOMERANG);});}}),
});
areaTable[JABU_JABUS_BELLY_GREEN_TENTACLE] = Area("Jabu Jabus Belly Green Tentacle", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_JABU_JABUS_BELLY_GREEN_TENTACLE] = Area("Jabu Jabus Belly Green Tentacle", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return Here(JABU_JABUS_BELLY_GREEN_TENTACLE, []{return CanUse(BOOMERANG);});}}),
Entrance(RR_JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return Here(RR_JABU_JABUS_BELLY_GREEN_TENTACLE, []{return CanUse(RG_BOOMERANG);});}}),
});
areaTable[JABU_JABUS_BELLY_BIGOCTO_ROOM] = Area("Jabu Jabus Belly Bigocto Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_JABU_JABUS_BELLY_BIGOCTO_ROOM] = Area("Jabu Jabus Belly Bigocto Room", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_ABOVE_BIGOCTO, {[]{return Here(JABU_JABUS_BELLY_BIGOCTO_ROOM, []{return (CanUse(BOOMERANG) || Nuts) && (CanUse(KOKIRI_SWORD) || CanUse(STICKS));});}}),
Entrance(RR_JABU_JABUS_BELLY_MAIN_LOWER, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO, {[]{return Here(RR_JABU_JABUS_BELLY_BIGOCTO_ROOM, []{return (CanUse(RG_BOOMERANG) || Nuts) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_STICKS));});}}),
});
areaTable[JABU_JABUS_BELLY_ABOVE_BIGOCTO] = Area("Jabu Jabus Belly Above Bigocto", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_JABU_JABUS_BELLY_ABOVE_BIGOCTO] = Area("Jabu Jabus Belly Above Bigocto", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
EventAccess(&NutPot, {[]{return true;}}),
}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_LIFT_UPPER, {[]{return CanUse(BOOMERANG);}}),
Entrance(RR_JABU_JABUS_BELLY_LIFT_UPPER, {[]{return CanUse(RG_BOOMERANG);}}),
});
areaTable[JABU_JABUS_BELLY_LIFT_UPPER] = Area("Jabu Jabus Belly Lift Upper", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_JABU_JABUS_BELLY_LIFT_UPPER] = Area("Jabu Jabus Belly Lift Upper", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_LIFT_LOWER, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_LIFT_LOWER, {[]{return true;}}),
});
areaTable[JABU_JABUS_BELLY_NEAR_BOSS_ROOM] = Area("Jabu Jabus Belly Near Boss Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM] = Area("Jabu Jabus Belly Near Boss Room", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_GS_NEAR_BOSS, {[]{return IsAdult || CanChildAttack;}}),
LocationAccess(RC_JABU_JABUS_BELLY_GS_NEAR_BOSS, {[]{return IsAdult || CanChildAttack;}}),
}, {
//Exits
Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return CanUse(BOOMERANG) || (LogicJabuNearBossRanged && ((IsAdult && (CanUse(HOOKSHOT) || CanUse(BOW))) || (IsChild && CanUse(SLINGSHOT)))) || (LogicJabuNearBossExplosives && (HasBombchus || (IsAdult && CanUse(HOVER_BOOTS) && Bombs)));}}),
Entrance(RR_JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return CanUse(RG_BOOMERANG) || (LogicJabuNearBossRanged && ((IsAdult && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW))) || (IsChild && CanUse(RG_FAIRY_SLINGSHOT)))) || (LogicJabuNearBossExplosives && (HasBombchus || (IsAdult && CanUse(RG_HOVER_BOOTS) && Bombs)));}}),
});
}
@@ -162,88 +162,88 @@ void AreaTable_Init_JabuJabusBelly() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::JabuJabusBelly.IsMQ()) {
areaTable[JABU_JABUS_BELLY_MQ_BEGINNING] = Area("Jabu Jabus Belly MQ Beginning", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_JABU_JABUS_BELLY_MQ_BEGINNING] = Area("Jabu Jabus Belly MQ Beginning", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&NutPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_MQ_MAP_CHEST, {[]{return CanBlastOrSmash;}}),
LocationAccess(JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, {[]{return IsChild && CanUse(SLINGSHOT);}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_MAP_CHEST, {[]{return CanBlastOrSmash;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST, {[]{return IsChild && CanUse(RG_FAIRY_SLINGSHOT);}}),
}, {
//Exits
Entrance(JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_MQ_MAIN, {[]{return Here(JABU_JABUS_BELLY_MQ_BEGINNING, []{return IsChild && CanUse(SLINGSHOT);});}}),
Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return Here(RR_JABU_JABUS_BELLY_MQ_BEGINNING, []{return IsChild && CanUse(RG_FAIRY_SLINGSHOT);});}}),
});
areaTable[JABU_JABUS_BELLY_MQ_MAIN] = Area("Jabu Jabus Belly MQ Main", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_JABU_JABUS_BELLY_MQ_MAIN] = Area("Jabu Jabus Belly MQ Main", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, {[]{return true;}}),
LocationAccess(JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, {[]{return (IsAdult && (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT))) || ChildCanAccess(JABU_JABUS_BELLY_MQ_BOSS_AREA);}}),
LocationAccess(JABU_JABUS_BELLY_MQ_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, {[]{return true;}}),
LocationAccess(JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return true;}}),
LocationAccess(JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, {[]{return true;}}),
LocationAccess(JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, {[]{return true;}}),
LocationAccess(JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(BOOMERANG));}}),
//Trick: CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(BOOMERANG))
LocationAccess(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, {[]{return (IsAdult && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT))) || ChildCanAccess(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA);}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(RG_BOOMERANG));}}),
//Trick: CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(RG_BOOMERANG))
}, {
//Exits
Entrance(JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_MQ_DEPTHS, {[]{return HasExplosives && IsChild && CanUse(BOOMERANG);}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_DEPTHS, {[]{return HasExplosives && IsChild && CanUse(RG_BOOMERANG);}}),
});
areaTable[JABU_JABUS_BELLY_MQ_DEPTHS] = Area("Jabu Jabus Belly MQ Depths", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_JABU_JABUS_BELLY_MQ_DEPTHS] = Area("Jabu Jabus Belly MQ Depths", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, {[]{return true;}}),
LocationAccess(JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, {[]{return Sticks || CanUse(DINS_FIRE);}}),
LocationAccess(JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, {[]{return (LogicLensJabuMQ || CanUse(LENS_OF_TRUTH)) || Here(JABU_JABUS_BELLY_MQ_MAIN, []{return IsAdult && CanUse(HOVER_BOOTS) && CanUse(HOOKSHOT);});}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM, {[]{return Sticks || CanUse(RG_DINS_FIRE);}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM, {[]{return (LogicLensJabuMQ || CanUse(RG_LENS_OF_TRUTH)) || Here(RR_JABU_JABUS_BELLY_MQ_MAIN, []{return IsAdult && CanUse(RG_HOVER_BOOTS) && CanUse(RG_HOOKSHOT);});}}),
}, {
//Exits
Entrance(JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_MQ_BOSS_AREA, {[]{return Sticks || (CanUse(DINS_FIRE) && KokiriSword);}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA, {[]{return Sticks || (CanUse(RG_DINS_FIRE) && KokiriSword);}}),
});
areaTable[JABU_JABUS_BELLY_MQ_BOSS_AREA] = Area("Jabu Jabus Belly MQ Boss Area", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_JABU_JABUS_BELLY_MQ_BOSS_AREA] = Area("Jabu Jabus Belly MQ Boss Area", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(JABU_JABUS_BELLY_MQ_COW, {[]{return CanPlay(EponasSong);}}),
LocationAccess(JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return true;}}),
LocationAccess(JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_COW, {[]{return CanPlay(EponasSong);}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return true;}}),
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return true;}}),
}, {
//Exits
Entrance(JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return CanUse(SLINGSHOT);}}),
Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, {[]{return CanUse(RG_FAIRY_SLINGSHOT);}}),
});
}
/*---------------------------
| BOSS ROOM |
---------------------------*/
areaTable[JABU_JABUS_BELLY_BOSS_ENTRYWAY] =
Area("Jabu Jabus Belly Boss Entryway", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY] =
Area("Jabu Jabus Belly Boss Entryway", "Jabu Jabus Belly", RHT_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(JABU_JABUS_BELLY_NEAR_BOSS_ROOM, { [] { return Dungeon::JabuJabusBelly.IsVanilla(); } }),
Entrance(JABU_JABUS_BELLY_MQ_BOSS_AREA, { [] { return Dungeon::JabuJabusBelly.IsMQ(); } }),
Entrance(JABU_JABUS_BELLY_BOSS_ROOM, { [] { return true; } }),
Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, { [] { return Dungeon::JabuJabusBelly.IsVanilla(); } }),
Entrance(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA, { [] { return Dungeon::JabuJabusBelly.IsMQ(); } }),
Entrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, { [] { return true; } }),
});
areaTable[JABU_JABUS_BELLY_BOSS_ROOM] =
Area("Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", NONE, NO_DAY_NIGHT_CYCLE,
areaTable[RR_JABU_JABUS_BELLY_BOSS_ROOM] =
Area("Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", RHT_NONE, NO_DAY_NIGHT_CYCLE,
{
// Events //todo: add pot kill trick
EventAccess(&JabuJabusBellyClear,
{ [] { return JabuJabusBellyClear || (HasBossSoul(BARINADE_BOSS_SOUL) && (CanUse(BOOMERANG) && CanJumpslash)); } }),
{ [] { return JabuJabusBellyClear || (HasBossSoul(RG_BARINADE_SOUL) && (CanUse(RG_BOOMERANG) && CanJumpslash)); } }),
},
{
// Locations
LocationAccess(JABU_JABUS_BELLY_BARINADE_HEART, { [] { return JabuJabusBellyClear; } }),
LocationAccess(BARINADE, { [] { return JabuJabusBellyClear; } }),
LocationAccess(RC_JABU_JABUS_BELLY_BARINADE_HEART, { [] { return JabuJabusBellyClear; } }),
LocationAccess(RC_BARINADE, { [] { return JabuJabusBellyClear; } }),
},
{
// Exits
Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, { [] { return false; } }),
Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, { [] { return false; } }),
});
}

View File

@@ -6,281 +6,287 @@ using namespace Logic;
using namespace Settings;
void AreaTable_Init_Kakariko() {
areaTable[KAKARIKO_VILLAGE] = Area("Kakariko Village", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_KAKARIKO_VILLAGE] = Area("Kakariko Village", "Kakariko Village", RHT_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&CojiroAccess, {[]{return CojiroAccess || (IsAdult && WakeUpAdultTalon);}}),
EventAccess(&BugRock, {[]{return true;}}),
EventAccess(&KakarikoVillageGateOpen, {[]{return KakarikoVillageGateOpen || (IsChild && (ZeldasLetter || OpenKakariko.Is(OPENKAKARIKO_OPEN)));}}),
}, {
//Locations
LocationAccess(SHEIK_IN_KAKARIKO, {[]{return IsAdult && ForestMedallion && FireMedallion && WaterMedallion;}}),
LocationAccess(KAK_ANJU_AS_CHILD, {[]{return IsChild && AtDay;}}),
LocationAccess(KAK_ANJU_AS_ADULT, {[]{return IsAdult && AtDay;}}),
LocationAccess(KAK_TRADE_POCKET_CUCCO, {[]{return IsAdult && AtDay && PocketEgg && WakeUpAdultTalon;}}),
LocationAccess(KAK_GS_HOUSE_UNDER_CONSTRUCTION, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(KAK_GS_SKULLTULA_HOUSE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(KAK_GS_GUARDS_HOUSE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(KAK_GS_TREE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(KAK_GS_WATCHTOWER, {[]{return IsChild && (Slingshot || HasBombchus || CanUse(BOW) || CanUse(LONGSHOT) || (LogicKakarikoTowerGS && CanJumpslash)) && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_SHEIK_IN_KAKARIKO, {[]{return IsAdult && ForestMedallion && FireMedallion && WaterMedallion;}}),
LocationAccess(RC_KAK_ANJU_AS_CHILD, {[]{return IsChild && AtDay;}}),
LocationAccess(RC_KAK_ANJU_AS_ADULT, {[]{return IsAdult && AtDay;}}),
LocationAccess(RC_KAK_TRADE_POCKET_CUCCO, {[]{return IsAdult && AtDay && PocketEgg && WakeUpAdultTalon;}}),
LocationAccess(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_KAK_GS_SKULLTULA_HOUSE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_KAK_GS_GUARDS_HOUSE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_KAK_GS_TREE, {[]{return IsChild && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_KAK_GS_WATCHTOWER, {[]{return IsChild && (Slingshot || HasBombchus || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT) || (LogicKakarikoTowerGS && CanJumpslash)) && AtNight && CanGetNightTimeGS;}}),
}, {
//Exits
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(KAK_CARPENTER_BOSS_HOUSE, {[]{return true;}}),
Entrance(KAK_HOUSE_OF_SKULLTULA, {[]{return true;}}),
Entrance(KAK_IMPAS_HOUSE, {[]{return true;}}),
Entrance(KAK_WINDMILL, {[]{return true;}}),
Entrance(KAK_BAZAAR, {[]{return IsAdult && AtDay;}}),
Entrance(KAK_SHOOTING_GALLERY, {[]{return IsAdult && AtDay;}}),
Entrance(BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return DrainWell && (IsChild || ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF));}}),
Entrance(KAK_POTION_SHOP_FRONT, {[]{return AtDay || IsChild;}}),
Entrance(KAK_REDEAD_GROTTO, {[]{return CanOpenBombGrotto;}}),
Entrance(KAK_IMPAS_LEDGE, {[]{return (IsChild && AtDay) || CanUse(HOOKSHOT) || (IsAdult && LogicVisibleCollision);}}),
Entrance(KAK_ROOFTOP, {[]{return CanUse(HOOKSHOT) || (LogicManOnRoof && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(BOW) || CanUse(LONGSHOT)));}}),
Entrance(KAK_IMPAS_ROOFTOP, {[]{return CanUse(HOOKSHOT) || (LogicKakarikoRooftopGS && CanUse(HOVER_BOOTS));}}),
Entrance(THE_GRAVEYARD, {[]{return true;}}),
Entrance(KAK_BEHIND_GATE, {[]{return IsAdult || (KakarikoVillageGateOpen);}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_KAK_CARPENTER_BOSS_HOUSE, {[]{return true;}}),
Entrance(RR_KAK_HOUSE_OF_SKULLTULA, {[]{return true;}}),
Entrance(RR_KAK_IMPAS_HOUSE, {[]{return true;}}),
Entrance(RR_KAK_WINDMILL, {[]{return true;}}),
Entrance(RR_KAK_BAZAAR, {[]{return IsAdult && AtDay;}}),
Entrance(RR_KAK_SHOOTING_GALLERY, {[]{return IsAdult && AtDay;}}),
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return DrainWell && (IsChild || ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF));}}),
Entrance(RR_KAK_POTION_SHOP_FRONT, {[]{return AtDay || IsChild;}}),
Entrance(RR_KAK_REDEAD_GROTTO, {[]{return CanOpenBombGrotto;}}),
Entrance(RR_KAK_IMPAS_LEDGE, {[]{return (IsChild && AtDay) || CanUse(RG_HOOKSHOT) || (IsAdult && LogicVisibleCollision);}}),
Entrance(RR_KAK_ROOFTOP, {[]{return CanUse(RG_HOOKSHOT) || (LogicManOnRoof && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(RG_FAIRY_BOW) || CanUse(RG_LONGSHOT)));}}),
Entrance(RR_KAK_IMPAS_ROOFTOP, {[]{return CanUse(RG_HOOKSHOT) || (LogicKakarikoRooftopGS && CanUse(RG_HOVER_BOOTS));}}),
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
Entrance(RR_KAK_BEHIND_GATE, {[]{return IsAdult || (KakarikoVillageGateOpen);}}),
});
areaTable[KAK_IMPAS_LEDGE] = Area("Kak Impas Ledge", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_KAK_IMPAS_LEDGE] = Area("Kak Impas Ledge", "Kakariko Village", RHT_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KAK_IMPAS_HOUSE_BACK, {[]{return true;}}),
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_KAK_IMPAS_HOUSE_BACK, {[]{return true;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_IMPAS_ROOFTOP] = Area("Kak Impas Rooftop", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KAK_IMPAS_ROOFTOP] = Area("Kak Impas Rooftop", "Kakariko Village", RHT_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_GS_ABOVE_IMPAS_HOUSE, {[]{return IsAdult && AtNight && CanGetNightTimeGS && (CanJumpslash || CanUseProjectile);}}),
LocationAccess(RC_KAK_GS_ABOVE_IMPAS_HOUSE, {[]{return IsAdult && AtNight && CanGetNightTimeGS && (CanJumpslash || CanUseProjectile);}}),
}, {
//Exits
Entrance(KAK_IMPAS_LEDGE, {[]{return true;}}),
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_KAK_IMPAS_LEDGE, {[]{return true;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_ROOFTOP] = Area("Kak Rooftop", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KAK_ROOFTOP] = Area("Kak Rooftop", "Kakariko Village", RHT_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_MAN_ON_ROOF, {[]{return true;}}),
LocationAccess(RC_KAK_MAN_ON_ROOF, {[]{return true;}}),
}, {
//Exits
Entrance(KAK_BACKYARD, {[]{return true;}}),
Entrance(RR_KAK_BACKYARD, {[]{return true;}}),
});
areaTable[KAK_BACKYARD] = Area("Kak Backyard", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_KAK_BACKYARD] = Area("Kak Backyard", "Kakariko Village", RHT_KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(KAK_OPEN_GROTTO, {[]{return true;}}),
Entrance(KAK_ODD_POTION_BUILDING, {[]{return IsAdult;}}),
Entrance(KAK_POTION_SHOP_BACK, {[]{return IsAdult && AtDay;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_KAK_OPEN_GROTTO, {[]{return true;}}),
Entrance(RR_KAK_ODD_POTION_BUILDING, {[]{return IsAdult;}}),
Entrance(RR_KAK_POTION_SHOP_BACK, {[]{return IsAdult && AtDay;}}),
});
areaTable[KAK_CARPENTER_BOSS_HOUSE] = Area("Kak Carpenter Boss House", "Kak Carpenter Boss House", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_KAK_CARPENTER_BOSS_HOUSE] = Area("Kak Carpenter Boss House", "Kak Carpenter Boss House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&WakeUpAdultTalon, {[]{return WakeUpAdultTalon || (IsAdult && PocketEgg);}}),
}, {}, {
//Exits
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_HOUSE_OF_SKULLTULA] = Area("Kak House of Skulltula", "Kak House of Skulltula", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KAK_HOUSE_OF_SKULLTULA] = Area("Kak House of Skulltula", "Kak House of Skulltula", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_10_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 10;}}),
LocationAccess(KAK_20_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 20;}}),
LocationAccess(KAK_30_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 30;}}),
LocationAccess(KAK_40_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 40;}}),
LocationAccess(KAK_50_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 50;}}),
LocationAccess(KAK_100_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 100;}})
LocationAccess(RC_KAK_10_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 10;}}),
LocationAccess(RC_KAK_20_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 20;}}),
LocationAccess(RC_KAK_30_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 30;}}),
LocationAccess(RC_KAK_40_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 40;}}),
LocationAccess(RC_KAK_50_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 50;}}),
LocationAccess(RC_KAK_100_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 100;}})
}, {
//Exits
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_IMPAS_HOUSE] = Area("Kak Impas House", "Kak Impas House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_KAK_IMPAS_HOUSE] = Area("Kak Impas House", "Kak Impas House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_IMPAS_HOUSE_BACK] = Area("Kak Impas House Back", "Kak Impas House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KAK_IMPAS_HOUSE_BACK] = Area("Kak Impas House Back", "Kak Impas House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_IMPAS_HOUSE_FREESTANDING_POH, {[]{return true;}}),
LocationAccess(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, {[]{return true;}}),
}, {
//Exits
Entrance(KAK_IMPAS_LEDGE, {[]{return true;}}),
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
Entrance(RR_KAK_IMPAS_LEDGE, {[]{return true;}}),
Entrance(RR_KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
});
areaTable[KAK_IMPAS_HOUSE_NEAR_COW] = Area("Kak Impas House Near Cow", "Kak Impas House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KAK_IMPAS_HOUSE_NEAR_COW] = Area("Kak Impas House Near Cow", "Kak Impas House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_IMPAS_HOUSE_COW, {[]{return CanPlay(EponasSong);}}),
LocationAccess(RC_KAK_IMPAS_HOUSE_COW, {[]{return CanPlay(EponasSong);}}),
}, {});
areaTable[KAK_WINDMILL] = Area("Kak Windmill", "Windmill and Dampes Grave", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_KAK_WINDMILL] = Area("Kak Windmill", "Windmill and Dampes Grave", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DrainWell, {[]{return DrainWell || (IsChild && CanPlay(SongOfStorms));}}),
}, {
//Locations
LocationAccess(KAK_WINDMILL_FREESTANDING_POH, {[]{return CanUse(BOOMERANG) || DampesWindmillAccess || (IsAdult && LogicAdultWindmillPoH) || (IsChild && CanJumpslash && LogicChildWindmillPoH);}}),
LocationAccess(RC_KAK_WINDMILL_FREESTANDING_POH, {[]{return CanUse(RG_BOOMERANG) || DampesWindmillAccess || (IsAdult && LogicAdultWindmillPoH) || (IsChild && CanJumpslash && LogicChildWindmillPoH);}}),
//PoH as child not added to trick options yet (needs uncommenting in randomizer_tricks.cpp)
LocationAccess(SONG_FROM_WINDMILL, {[]{return IsAdult && Ocarina;}}),
LocationAccess(RC_SONG_FROM_WINDMILL, {[]{return IsAdult && Ocarina;}}),
}, {
//Exits
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_BAZAAR] = Area("Kak Bazaar", "Kak Bazaar", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KAK_BAZAAR] = Area("Kak Bazaar", "Kak Bazaar", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_BAZAAR_ITEM_1, {[]{return true;}}),
LocationAccess(KAK_BAZAAR_ITEM_2, {[]{return true;}}),
LocationAccess(KAK_BAZAAR_ITEM_3, {[]{return true;}}),
LocationAccess(KAK_BAZAAR_ITEM_4, {[]{return true;}}),
LocationAccess(KAK_BAZAAR_ITEM_5, {[]{return true;}}),
LocationAccess(KAK_BAZAAR_ITEM_6, {[]{return true;}}),
LocationAccess(KAK_BAZAAR_ITEM_7, {[]{return true;}}),
LocationAccess(KAK_BAZAAR_ITEM_8, {[]{return true;}}),
LocationAccess(RC_KAK_BAZAAR_ITEM_1, {[]{return true;}}),
LocationAccess(RC_KAK_BAZAAR_ITEM_2, {[]{return true;}}),
LocationAccess(RC_KAK_BAZAAR_ITEM_3, {[]{return true;}}),
LocationAccess(RC_KAK_BAZAAR_ITEM_4, {[]{return true;}}),
LocationAccess(RC_KAK_BAZAAR_ITEM_5, {[]{return true;}}),
LocationAccess(RC_KAK_BAZAAR_ITEM_6, {[]{return true;}}),
LocationAccess(RC_KAK_BAZAAR_ITEM_7, {[]{return true;}}),
LocationAccess(RC_KAK_BAZAAR_ITEM_8, {[]{return true;}}),
}, {
//Exits
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_SHOOTING_GALLERY] = Area("Kak Shooting Gallery", "Kak Shooting Gallery", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KAK_SHOOTING_GALLERY] = Area("Kak Shooting Gallery", "Kak Shooting Gallery", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_SHOOTING_GALLERY_REWARD, {[]{return IsAdult && Bow;}}),
LocationAccess(RC_KAK_SHOOTING_GALLERY_REWARD, {[]{return IsAdult && Bow;}}),
}, {
//Exits
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[KAK_POTION_SHOP_FRONT] = Area("Kak Potion Shop Front", "Kak Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KAK_POTION_SHOP_FRONT] = Area("Kak Potion Shop Front", "Kak Potion Shop", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KAK_POTION_SHOP_ITEM_1, {[]{return IsAdult;}}),
LocationAccess(KAK_POTION_SHOP_ITEM_2, {[]{return IsAdult;}}),
LocationAccess(KAK_POTION_SHOP_ITEM_3, {[]{return IsAdult;}}),
LocationAccess(KAK_POTION_SHOP_ITEM_4, {[]{return IsAdult;}}),
LocationAccess(KAK_POTION_SHOP_ITEM_5, {[]{return IsAdult;}}),
LocationAccess(KAK_POTION_SHOP_ITEM_6, {[]{return IsAdult;}}),
LocationAccess(KAK_POTION_SHOP_ITEM_7, {[]{return IsAdult;}}),
LocationAccess(KAK_POTION_SHOP_ITEM_8, {[]{return IsAdult;}}),
LocationAccess(RC_KAK_POTION_SHOP_ITEM_1, {[]{return IsAdult;}}),
LocationAccess(RC_KAK_POTION_SHOP_ITEM_2, {[]{return IsAdult;}}),
LocationAccess(RC_KAK_POTION_SHOP_ITEM_3, {[]{return IsAdult;}}),
LocationAccess(RC_KAK_POTION_SHOP_ITEM_4, {[]{return IsAdult;}}),
LocationAccess(RC_KAK_POTION_SHOP_ITEM_5, {[]{return IsAdult;}}),
LocationAccess(RC_KAK_POTION_SHOP_ITEM_6, {[]{return IsAdult;}}),
LocationAccess(RC_KAK_POTION_SHOP_ITEM_7, {[]{return IsAdult;}}),
LocationAccess(RC_KAK_POTION_SHOP_ITEM_8, {[]{return IsAdult;}}),
}, {
//Exits
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(KAK_POTION_SHOP_BACK, {[]{return IsAdult;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_KAK_POTION_SHOP_BACK, {[]{return IsAdult;}}),
});
areaTable[KAK_POTION_SHOP_BACK] = Area("Kak Potion Shop Back", "Kak Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_KAK_POTION_SHOP_BACK] = Area("Kak Potion Shop Back", "Kak Potion Shop", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KAK_BACKYARD, {[]{return IsAdult;}}),
Entrance(KAK_POTION_SHOP_FRONT, {[]{return true;}}),
Entrance(RR_KAK_BACKYARD, {[]{return IsAdult;}}),
Entrance(RR_KAK_POTION_SHOP_FRONT, {[]{return true;}}),
});
areaTable[KAK_ODD_POTION_BUILDING] = Area("Kak Granny's Potion Shop", "Kak Granny's Potion Shop", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_KAK_ODD_POTION_BUILDING] =
Area("Kak Granny's Potion Shop", "Kak Granny's Potion Shop", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
// Events
EventAccess(&OddPoulticeAccess, { [] {
return OddPoulticeAccess || (IsAdult && (OddMushroomAccess || (OddMushroom && DisableTradeRevert)));
} }),
},
{
LocationAccess(RC_KAK_TRADE_ODD_MUSHROOM, { [] { return IsAdult && OddMushroom; } }),
LocationAccess(RC_KAK_GRANNYS_SHOP, { [] { return IsAdult && OddMushroom && AdultsWallet; } }),
},
{
// Exits
Entrance(RR_KAK_BACKYARD, { [] { return true; } }),
});
areaTable[RR_KAK_REDEAD_GROTTO] = Area("Kak Redead Grotto", "Kak Redead Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(RC_KAK_REDEAD_GROTTO_CHEST, {[]{return IsAdult || (Sticks || KokiriSword || CanUse(RG_DINS_FIRE) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD));}}),
}, {
//Exits
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
});
areaTable[RR_KAK_OPEN_GROTTO] = Area("Kak Open Grotto", "Kak Open Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(RC_KAK_OPEN_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(RC_KAK_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(RR_KAK_BACKYARD, {[]{return true;}}),
});
areaTable[RR_THE_GRAVEYARD] = Area("The Graveyard", "The Graveyard", RHT_THE_GRAVEYARD, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&OddPoulticeAccess, {[]{return OddPoulticeAccess || (IsAdult && (OddMushroomAccess || (OddMushroom && DisableTradeRevert)));}}),
}, {
LocationAccess(KAK_TRADE_ODD_MUSHROOM, {[]{return IsAdult && OddMushroom;}}),
LocationAccess(KAK_GRANNYS_SHOP, {[]{return IsAdult && OddMushroom && AdultsWallet;}}),
}, {
//Exits
Entrance(KAK_BACKYARD, {[]{return true;}}),
});
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));}}),
}, {
//Exits
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
});
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;}}),
}, {
//Exits
Entrance(KAK_BACKYARD, {[]{return true;}}),
});
areaTable[THE_GRAVEYARD] = Area("The Graveyard", "The Graveyard", THE_GRAVEYARD, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || (CanUse(STICKS) && AtDay);}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(THE_GRAVEYARD) && CanPlay(SongOfStorms));}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || (CanUse(RG_STICKS) && AtDay);}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_THE_GRAVEYARD) && CanPlay(SongOfStorms));}}),
EventAccess(&BugRock, {[]{return true;}}),
}, {
//Locations
LocationAccess(GRAVEYARD_FREESTANDING_POH, {[]{return (IsAdult && CanPlantBean(THE_GRAVEYARD)) || CanUse(LONGSHOT) || (LogicGraveyardPoH && CanUse(BOOMERANG));}}),
LocationAccess(GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, {[]{return IsChild && AtNight;}}), //TODO: This needs to change
LocationAccess(GRAVEYARD_GS_WALL, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(GRAVEYARD_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(RC_GRAVEYARD_FREESTANDING_POH, {[]{return (IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || CanUse(RG_LONGSHOT) || (LogicGraveyardPoH && CanUse(RG_BOOMERANG));}}),
LocationAccess(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, {[]{return IsChild && AtNight;}}), //TODO: This needs to change
LocationAccess(RC_GRAVEYARD_GS_WALL, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_GRAVEYARD_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
}, {
//Exits
Entrance(GRAVEYARD_SHIELD_GRAVE, {[]{return IsAdult || AtNight;}}),
Entrance(GRAVEYARD_COMPOSERS_GRAVE, {[]{return CanPlay(ZeldasLullaby);}}),
Entrance(GRAVEYARD_HEART_PIECE_GRAVE, {[]{return IsAdult || AtNight;}}),
Entrance(GRAVEYARD_DAMPES_GRAVE, {[]{return IsAdult;}}),
Entrance(GRAVEYARD_DAMPES_HOUSE, {[]{return IsAdult || AtDampeTime;}}), //TODO: This needs to be handled
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(GRAVEYARD_WARP_PAD_REGION, {[]{return false;}}),
Entrance(RR_GRAVEYARD_SHIELD_GRAVE, {[]{return IsAdult || AtNight;}}),
Entrance(RR_GRAVEYARD_COMPOSERS_GRAVE, {[]{return CanPlay(ZeldasLullaby);}}),
Entrance(RR_GRAVEYARD_HEART_PIECE_GRAVE, {[]{return IsAdult || AtNight;}}),
Entrance(RR_GRAVEYARD_DAMPES_GRAVE, {[]{return IsAdult;}}),
Entrance(RR_GRAVEYARD_DAMPES_HOUSE, {[]{return IsAdult || AtDampeTime;}}), //TODO: This needs to be handled
Entrance(RR_KAKARIKO_VILLAGE, {[]{return true;}}),
Entrance(RR_GRAVEYARD_WARP_PAD_REGION, {[]{return false;}}),
});
areaTable[GRAVEYARD_SHIELD_GRAVE] = Area("Graveyard Shield Grave", "Graveyard Shield Grave", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GRAVEYARD_SHIELD_GRAVE] = Area("Graveyard Shield Grave", "Graveyard Shield Grave", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GRAVEYARD_SHIELD_GRAVE_CHEST, {[]{return true;}}),
LocationAccess(RC_GRAVEYARD_SHIELD_GRAVE_CHEST, {[]{return true;}}),
//Free Fairies
}, {
//Exits
Entrance(THE_GRAVEYARD, {[]{return true;}}),
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
});
areaTable[GRAVEYARD_HEART_PIECE_GRAVE] = Area("Graveyard Heart Piece Grave", "Graveyard Heart Piece Grave", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GRAVEYARD_HEART_PIECE_GRAVE] = Area("Graveyard Heart Piece Grave", "Graveyard Heart Piece Grave", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GRAVEYARD_HEART_PIECE_GRAVE_CHEST, {[]{return CanPlay(SunsSong);}}),
LocationAccess(RC_GRAVEYARD_HEART_PIECE_GRAVE_CHEST, {[]{return CanPlay(SunsSong);}}),
}, {
//Exits
Entrance(THE_GRAVEYARD, {[]{return true;}}),
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
});
areaTable[GRAVEYARD_COMPOSERS_GRAVE] = Area("Graveyard Composers Grave", "Graveyard Composers Grave", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_GRAVEYARD_COMPOSERS_GRAVE] = Area("Graveyard Composers Grave", "Graveyard Composers Grave", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(GRAVEYARD_COMPOSERS_GRAVE_CHEST, {[]{return HasFireSource;}}),
LocationAccess(SONG_FROM_COMPOSERS_GRAVE, {[]{return IsAdult || (Slingshot || Boomerang || Sticks || HasExplosives || KokiriSword || CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || CanUse(BOW) || CanUse(HOOKSHOT));}}),
LocationAccess(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, {[]{return HasFireSource;}}),
LocationAccess(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, {[]{return IsAdult || (Slingshot || Boomerang || Sticks || HasExplosives || KokiriSword || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT));}}),
}, {
//Exits
Entrance(THE_GRAVEYARD, {[]{return true;}}),
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
});
areaTable[GRAVEYARD_DAMPES_GRAVE] = Area("Graveyard Dampes Grave", "Windmill and Dampes Grave", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GRAVEYARD_DAMPES_GRAVE] = Area("Graveyard Dampes Grave", "Windmill and Dampes Grave", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&NutPot, {[]{return true;}}),
EventAccess(&DampesWindmillAccess, {[]{return DampesWindmillAccess || (IsAdult && CanPlay(SongOfTime));}}),
}, {
//Locations
LocationAccess(GRAVEYARD_HOOKSHOT_CHEST, {[]{return true;}}),
LocationAccess(GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, {[]{return IsAdult || LogicChildDampeRacePoH;}}),
LocationAccess(RC_GRAVEYARD_HOOKSHOT_CHEST, {[]{return true;}}),
LocationAccess(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, {[]{return IsAdult || LogicChildDampeRacePoH;}}),
}, {
//Exits
Entrance(THE_GRAVEYARD, {[]{return true;}}),
Entrance(KAK_WINDMILL, {[]{return IsAdult && CanPlay(SongOfTime);}}),
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
Entrance(RR_KAK_WINDMILL, {[]{return IsAdult && CanPlay(SongOfTime);}}),
});
areaTable[GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "Graveyard Dampes House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "Graveyard Dampes House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(THE_GRAVEYARD, {[]{return true;}}),
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
});
areaTable[GRAVEYARD_WARP_PAD_REGION] = Area("Graveyard Warp Pad Region", "Graveyard", THE_GRAVEYARD, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_GRAVEYARD_WARP_PAD_REGION] = Area("Graveyard Warp Pad Region", "Graveyard", RHT_THE_GRAVEYARD, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
}, {
//Locations
LocationAccess(GRAVEYARD_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_GY_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(THE_GRAVEYARD, {[]{return true;}}),
Entrance(SHADOW_TEMPLE_ENTRYWAY, {[]{return CanUse(DINS_FIRE) || (LogicShadowFireArrowEntry && IsAdult && CanUse(FIRE_ARROWS));}}),
Entrance(RR_THE_GRAVEYARD, {[]{return true;}}),
Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_DINS_FIRE) || (LogicShadowFireArrowEntry && IsAdult && CanUse(RG_FIRE_ARROWS));}}),
});
areaTable[KAK_BEHIND_GATE] = Area("Kak Behind Gate", "Kakariko Village", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_KAK_BEHIND_GATE] = Area("Kak Behind Gate", "Kakariko Village", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KAKARIKO_VILLAGE, {[]{return IsAdult || LogicVisibleCollision || KakarikoVillageGateOpen || OpenKakariko.Is(OPENKAKARIKO_OPEN);}}),
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
Entrance(RR_KAKARIKO_VILLAGE, {[]{return IsAdult || LogicVisibleCollision || KakarikoVillageGateOpen || OpenKakariko.Is(OPENKAKARIKO_OPEN);}}),
Entrance(RR_DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
});
}

View File

@@ -6,111 +6,111 @@ using namespace Logic;
using namespace Settings;
void AreaTable_Init_LostWoods() {
areaTable[KOKIRI_FOREST] = Area("Kokiri Forest", "Kokiri Forest", KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_KOKIRI_FOREST] = Area("Kokiri Forest", "Kokiri Forest", RHT_KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(KOKIRI_FOREST) && CanPlay(SongOfStorms));}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_KOKIRI_FOREST) && CanPlay(SongOfStorms));}}),
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
EventAccess(&ShowedMidoSwordAndShield, {[]{return ShowedMidoSwordAndShield || (IsChild && KokiriSword && DekuShield);}}),
}, {
//Locations
LocationAccess(KF_KOKIRI_SWORD_CHEST, {[]{return IsChild;}}),
LocationAccess(KF_GS_KNOW_IT_ALL_HOUSE, {[]{return IsChild && CanChildAttack && AtNight && (HasNightStart || CanLeaveForest || CanPlay(SunsSong)) && CanGetNightTimeGS;}}),
LocationAccess(KF_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(KF_GS_HOUSE_OF_TWINS, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || (LogicAdultKokiriGS && CanUse(HOVER_BOOTS))) && CanGetNightTimeGS;}}),
LocationAccess(KF_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_KF_KOKIRI_SWORD_CHEST, {[]{return IsChild;}}),
LocationAccess(RC_KF_GS_KNOW_IT_ALL_HOUSE, {[]{return IsChild && CanChildAttack && AtNight && (HasNightStart || CanLeaveForest || CanPlay(SunsSong)) && CanGetNightTimeGS;}}),
LocationAccess(RC_KF_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(RC_KF_GS_HOUSE_OF_TWINS, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || (LogicAdultKokiriGS && CanUse(RG_HOVER_BOOTS))) && CanGetNightTimeGS;}}),
LocationAccess(RC_KF_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(KF_LINKS_HOUSE, {[]{return true;}}),
Entrance(KF_MIDOS_HOUSE, {[]{return true;}}),
Entrance(KF_SARIAS_HOUSE, {[]{return true;}}),
Entrance(KF_HOUSE_OF_TWINS, {[]{return true;}}),
Entrance(KF_KNOW_IT_ALL_HOUSE, {[]{return true;}}),
Entrance(KF_KOKIRI_SHOP, {[]{return true;}}),
Entrance(KF_OUTSIDE_DEKU_TREE, {[]{return IsAdult || OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield;}}),
Entrance(THE_LOST_WOODS, {[]{return true;}}),
Entrance(LW_BRIDGE_FROM_FOREST, {[]{return IsAdult || OpenForest.IsNot(OPENFOREST_CLOSED) || DekuTreeClear;}}),
Entrance(KF_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
Entrance(RR_KF_LINKS_HOUSE, {[]{return true;}}),
Entrance(RR_KF_MIDOS_HOUSE, {[]{return true;}}),
Entrance(RR_KF_SARIAS_HOUSE, {[]{return true;}}),
Entrance(RR_KF_HOUSE_OF_TWINS, {[]{return true;}}),
Entrance(RR_KF_KNOW_IT_ALL_HOUSE, {[]{return true;}}),
Entrance(RR_KF_KOKIRI_SHOP, {[]{return true;}}),
Entrance(RR_KF_OUTSIDE_DEKU_TREE, {[]{return IsAdult || OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield;}}),
Entrance(RR_THE_LOST_WOODS, {[]{return true;}}),
Entrance(RR_LW_BRIDGE_FROM_FOREST, {[]{return IsAdult || OpenForest.IsNot(OPENFOREST_CLOSED) || DekuTreeClear;}}),
Entrance(RR_KF_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
});
areaTable[KF_OUTSIDE_DEKU_TREE] = Area("KF Outside Deku Tree", "Kokiri Forest", KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_KF_OUTSIDE_DEKU_TREE] = Area("KF Outside Deku Tree", "Kokiri Forest", RHT_KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || ((IsAdult && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF)) || KokiriSword || Boomerang);}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || ((IsAdult && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF)) || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(DINS_FIRE));}}),
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || ((IsAdult && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF)) || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(RG_DINS_FIRE));}}),
EventAccess(&ShowedMidoSwordAndShield, {[]{return ShowedMidoSwordAndShield || (IsChild && KokiriSword && DekuShield);}}),
}, {
//Locations
LocationAccess(KF_DEKU_TREE_GOSSIP_STONE_LEFT, {[]{return true;}}),
LocationAccess(KF_DEKU_TREE_GOSSIP_STONE_RIGHT, {[]{return true;}}),
LocationAccess(RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(DEKU_TREE_ENTRYWAY, {[]{return IsChild || (ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF) && (OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield));}}),
Entrance(KOKIRI_FOREST, {[]{return IsAdult || OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield;}}),
Entrance(RR_DEKU_TREE_ENTRYWAY, {[]{return IsChild || (ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF) && (OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield));}}),
Entrance(RR_KOKIRI_FOREST, {[]{return IsAdult || OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield;}}),
});
areaTable[KF_LINKS_HOUSE] = Area("KF Link's House", "KF Link's House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KF_LINKS_HOUSE] = Area("KF Link's House", "KF Link's House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KF_LINKS_HOUSE_COW, {[]{return IsAdult && CanPlay(EponasSong) && LinksCow;}}),
LocationAccess(RC_KF_LINKS_HOUSE_COW, {[]{return IsAdult && CanPlay(EponasSong) && LinksCow;}}),
}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}})
Entrance(RR_KOKIRI_FOREST, {[]{return true;}})
});
areaTable[KF_MIDOS_HOUSE] = Area("KF Mido's House", "KF Mido's House", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KF_MIDOS_HOUSE] = Area("KF Mido's House", "KF Mido's House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KF_MIDOS_TOP_LEFT_CHEST, {[]{return true;}}),
LocationAccess(KF_MIDOS_TOP_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(KF_MIDOS_BOTTOM_LEFT_CHEST, {[]{return true;}}),
LocationAccess(KF_MIDOS_BOTTOM_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(RC_KF_MIDOS_TOP_LEFT_CHEST, {[]{return true;}}),
LocationAccess(RC_KF_MIDOS_TOP_RIGHT_CHEST, {[]{return true;}}),
LocationAccess(RC_KF_MIDOS_BOTTOM_LEFT_CHEST, {[]{return true;}}),
LocationAccess(RC_KF_MIDOS_BOTTOM_RIGHT_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}}),
Entrance(RR_KOKIRI_FOREST, {[]{return true;}}),
});
areaTable[KF_SARIAS_HOUSE] = Area("KF Saria's House", "KF Saria's House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_KF_SARIAS_HOUSE] = Area("KF Saria's House", "KF Saria's House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}}),
Entrance(RR_KOKIRI_FOREST, {[]{return true;}}),
});
areaTable[KF_HOUSE_OF_TWINS] = Area("KF House of Twins", "KF House of Twins", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_KF_HOUSE_OF_TWINS] = Area("KF House of Twins", "KF House of Twins", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}}),
Entrance(RR_KOKIRI_FOREST, {[]{return true;}}),
});
areaTable[KF_KNOW_IT_ALL_HOUSE] = Area("KF Know It All House", "KF Know It All House", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_KF_KNOW_IT_ALL_HOUSE] = Area("KF Know It All House", "KF Know It All House", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}}),
Entrance(RR_KOKIRI_FOREST, {[]{return true;}}),
});
areaTable[KF_KOKIRI_SHOP] = Area("KF Kokiri Shop", "KF Kokiri Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_KF_KOKIRI_SHOP] = Area("KF Kokiri Shop", "KF Kokiri Shop", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(KF_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(KF_SHOP_ITEM_2, {[]{return true;}}),
LocationAccess(KF_SHOP_ITEM_3, {[]{return true;}}),
LocationAccess(KF_SHOP_ITEM_4, {[]{return true;}}),
LocationAccess(KF_SHOP_ITEM_5, {[]{return true;}}),
LocationAccess(KF_SHOP_ITEM_6, {[]{return true;}}),
LocationAccess(KF_SHOP_ITEM_7, {[]{return true;}}),
LocationAccess(KF_SHOP_ITEM_8, {[]{return true;}}),
LocationAccess(RC_KF_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(RC_KF_SHOP_ITEM_2, {[]{return true;}}),
LocationAccess(RC_KF_SHOP_ITEM_3, {[]{return true;}}),
LocationAccess(RC_KF_SHOP_ITEM_4, {[]{return true;}}),
LocationAccess(RC_KF_SHOP_ITEM_5, {[]{return true;}}),
LocationAccess(RC_KF_SHOP_ITEM_6, {[]{return true;}}),
LocationAccess(RC_KF_SHOP_ITEM_7, {[]{return true;}}),
LocationAccess(RC_KF_SHOP_ITEM_8, {[]{return true;}}),
}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}}),
Entrance(RR_KOKIRI_FOREST, {[]{return true;}}),
});
areaTable[KF_STORMS_GROTTO] = Area("KF Storms Grotto", "KF Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[RR_KF_STORMS_GROTTO] = Area("KF Storms Grotto", "KF Storms Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(KF_STORMS_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(KF_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_KF_STORMS_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(RC_KF_STORMS_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}})
Entrance(RR_KOKIRI_FOREST, {[]{return true;}})
});
areaTable[LW_FOREST_EXIT] = Area("LW Forest Exit", "Lost Woods", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_LW_FOREST_EXIT] = Area("LW Forest Exit", "Lost Woods", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}})
Entrance(RR_KOKIRI_FOREST, {[]{return true;}})
});
areaTable[THE_LOST_WOODS] = Area("Lost Woods", "Lost Woods", THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_THE_LOST_WOODS] = Area("Lost Woods", "Lost Woods", RHT_THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&OddMushroomAccess, {[]{return OddMushroomAccess || (IsAdult && (CojiroAccess || Cojiro));}}),
EventAccess(&PoachersSawAccess, {[]{return PoachersSawAccess || (IsAdult && OddPoulticeAccess);}}),
@@ -119,132 +119,132 @@ void AreaTable_Init_LostWoods() {
EventAccess(&BugShrub, {[]{return IsChild && CanCutShrubs;}}),
}, {
//Locations
LocationAccess(LW_SKULL_KID, {[]{return IsChild && CanPlay(SariasSong);}}),
LocationAccess(LW_TRADE_COJIRO, {[]{return IsAdult && Cojiro;}}),
LocationAccess(LW_TRADE_ODD_POTION, {[]{return IsAdult && OddPoultice && Cojiro;}}),
LocationAccess(LW_OCARINA_MEMORY_GAME, {[]{return IsChild && Ocarina;}}),
LocationAccess(LW_TARGET_IN_WOODS, {[]{return IsChild && CanUse(SLINGSHOT);}}),
LocationAccess(LW_DEKU_SCRUB_NEAR_BRIDGE, {[]{return IsChild && CanStunDeku;}}),
LocationAccess(LW_GS_BEAN_PATCH_NEAR_BRIDGE, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(LW_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_LW_SKULL_KID, {[]{return IsChild && CanPlay(SariasSong);}}),
LocationAccess(RC_LW_TRADE_COJIRO, {[]{return IsAdult && Cojiro;}}),
LocationAccess(RC_LW_TRADE_ODD_POTION, {[]{return IsAdult && OddPoultice && Cojiro;}}),
LocationAccess(RC_LW_OCARINA_MEMORY_GAME, {[]{return IsChild && Ocarina;}}),
LocationAccess(RC_LW_TARGET_IN_WOODS, {[]{return IsChild && CanUse(RG_FAIRY_SLINGSHOT);}}),
LocationAccess(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, {[]{return IsChild && CanStunDeku;}}),
LocationAccess(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, {[]{return CanPlantBugs && CanChildAttack;}}),
LocationAccess(RC_LW_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(LW_FOREST_EXIT, {[]{return true;}}),
Entrance(GC_WOODS_WARP, {[]{return true;}}),
Entrance(LW_BRIDGE, {[]{return CanLeaveForest && ((IsAdult && (CanPlantBean(THE_LOST_WOODS) || LogicLostWoodsBridge)) || CanUse(HOVER_BOOTS) || CanUse(LONGSHOT));}}),
Entrance(ZORAS_RIVER, {[]{return CanLeaveForest && (CanDive || CanUse(IRON_BOOTS));}}),
Entrance(LW_BEYOND_MIDO, {[]{return IsChild || CanPlay(SariasSong) || LogicMidoBackflip;}}),
Entrance(LW_NEAR_SHORTCUTS_GROTTO, {[]{return Here(THE_LOST_WOODS, []{return CanBlastOrSmash;});}}),
Entrance(RR_LW_FOREST_EXIT, {[]{return true;}}),
Entrance(RR_GC_WOODS_WARP, {[]{return true;}}),
Entrance(RR_LW_BRIDGE, {[]{return CanLeaveForest && ((IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || LogicLostWoodsBridge)) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_LONGSHOT));}}),
Entrance(RR_ZORAS_RIVER, {[]{return CanLeaveForest && (CanDive || CanUse(RG_IRON_BOOTS));}}),
Entrance(RR_LW_BEYOND_MIDO, {[]{return IsChild || CanPlay(SariasSong) || LogicMidoBackflip;}}),
Entrance(RR_LW_NEAR_SHORTCUTS_GROTTO, {[]{return Here(RR_THE_LOST_WOODS, []{return CanBlastOrSmash;});}}),
});
areaTable[LW_BEYOND_MIDO] = Area("LW Beyond Mido", "Lost Woods", THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_LW_BEYOND_MIDO] = Area("LW Beyond Mido", "Lost Woods", RHT_THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(STICKS);}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(RG_STICKS);}}),
}, {
//Locations
LocationAccess(LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, {[]{return IsChild && CanStunDeku;}}),
LocationAccess(LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, {[]{return IsChild && CanStunDeku;}}),
LocationAccess(LW_GS_ABOVE_THEATER, {[]{return IsAdult && AtNight && (CanPlantBean(LW_BEYOND_MIDO) || (LogicLostWoodsGSBean && CanUse(HOOKSHOT) && (CanUse(LONGSHOT) || CanUse(BOW) || CanUse(SLINGSHOT) || HasBombchus || CanUse(DINS_FIRE)))) && CanGetNightTimeGS;}}),
LocationAccess(LW_GS_BEAN_PATCH_NEAR_THEATER, {[]{return CanPlantBugs && (CanChildAttack || (Scrubsanity.Is(SCRUBSANITY_OFF) && DekuShield));}}),
LocationAccess(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, {[]{return IsChild && CanStunDeku;}}),
LocationAccess(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, {[]{return IsChild && CanStunDeku;}}),
LocationAccess(RC_LW_GS_ABOVE_THEATER, {[]{return IsAdult && AtNight && (CanPlantBean(RR_LW_BEYOND_MIDO) || (LogicLostWoodsGSBean && CanUse(RG_HOOKSHOT) && (CanUse(RG_LONGSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || HasBombchus || CanUse(RG_DINS_FIRE)))) && CanGetNightTimeGS;}}),
LocationAccess(RC_LW_GS_BEAN_PATCH_NEAR_THEATER, {[]{return CanPlantBugs && (CanChildAttack || (Scrubsanity.Is(SCRUBSANITY_OFF) && DekuShield));}}),
}, {
//Exits
Entrance(LW_FOREST_EXIT, {[]{return true;}}),
Entrance(THE_LOST_WOODS, {[]{return IsChild || CanPlay(SariasSong);}}),
Entrance(SFM_ENTRYWAY, {[]{return true;}}),
Entrance(DEKU_THEATER, {[]{return true;}}),
Entrance(LW_SCRUBS_GROTTO, {[]{return Here(LW_BEYOND_MIDO, []{return CanBlastOrSmash;});}}),
Entrance(RR_LW_FOREST_EXIT, {[]{return true;}}),
Entrance(RR_THE_LOST_WOODS, {[]{return IsChild || CanPlay(SariasSong);}}),
Entrance(RR_SFM_ENTRYWAY, {[]{return true;}}),
Entrance(RR_DEKU_THEATER, {[]{return true;}}),
Entrance(RR_LW_SCRUBS_GROTTO, {[]{return Here(RR_LW_BEYOND_MIDO, []{return CanBlastOrSmash;});}}),
});
areaTable[LW_NEAR_SHORTCUTS_GROTTO] = Area("LW Near Shortcuts Grotto", "LW Near Shortcuts Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[RR_LW_NEAR_SHORTCUTS_GROTTO] = Area("LW Near Shortcuts Grotto", "LW Near Shortcuts Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(RC_LW_NEAR_SHORTCUTS_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(THE_LOST_WOODS, {[]{return true;}}),
Entrance(RR_THE_LOST_WOODS, {[]{return true;}}),
});
areaTable[DEKU_THEATER] = Area("Deku Theater", "Deku Theater", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_DEKU_THEATER] = Area("Deku Theater", "Deku Theater", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(DEKU_THEATER_SKULL_MASK, {[]{return IsChild && SkullMask;}}),
LocationAccess(DEKU_THEATER_MASK_OF_TRUTH, {[]{return IsChild && MaskOfTruth;}}),
LocationAccess(RC_DEKU_THEATER_SKULL_MASK, {[]{return IsChild && SkullMask;}}),
LocationAccess(RC_DEKU_THEATER_MASK_OF_TRUTH, {[]{return IsChild && MaskOfTruth;}}),
}, {
//Exits
Entrance(LW_BEYOND_MIDO, {[]{return true;}}),
Entrance(RR_LW_BEYOND_MIDO, {[]{return true;}}),
});
areaTable[LW_SCRUBS_GROTTO] = Area("LW Scrubs Grotto", "LW Scrubs Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_LW_SCRUBS_GROTTO] = Area("LW Scrubs Grotto", "LW Scrubs Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LW_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(LW_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
LocationAccess(RC_LW_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(RC_LW_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(LW_BEYOND_MIDO, {[]{return true;}}),
Entrance(RR_LW_BEYOND_MIDO, {[]{return true;}}),
});
areaTable[SFM_ENTRYWAY] = Area("SFM Entryway", "Sacred Forest Meadow", SACRED_FOREST_MEADOW, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SFM_ENTRYWAY] = Area("SFM Entryway", "Sacred Forest Meadow", RHT_SACRED_FOREST_MEADOW, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(LW_BEYOND_MIDO, {[]{return true;}}),
Entrance(SACRED_FOREST_MEADOW, {[]{return IsAdult || Slingshot || Sticks || KokiriSword || CanUse(DINS_FIRE) || CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);}}),
Entrance(SFM_WOLFOS_GROTTO, {[]{return CanOpenBombGrotto;}}),
Entrance(RR_LW_BEYOND_MIDO, {[]{return true;}}),
Entrance(RR_SACRED_FOREST_MEADOW, {[]{return IsAdult || Slingshot || Sticks || KokiriSword || CanUse(RG_DINS_FIRE) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
Entrance(RR_SFM_WOLFOS_GROTTO, {[]{return CanOpenBombGrotto;}}),
});
areaTable[SACRED_FOREST_MEADOW] = Area("Sacred Forest Meadow", "Sacred Forest Meadow", SACRED_FOREST_MEADOW, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_SACRED_FOREST_MEADOW] = Area("Sacred Forest Meadow", "Sacred Forest Meadow", RHT_SACRED_FOREST_MEADOW, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
}, {
//Locations
LocationAccess(SONG_FROM_SARIA, {[]{return IsChild && ZeldasLetter;}}),
LocationAccess(SHEIK_IN_FOREST, {[]{return IsAdult;}}),
LocationAccess(SFM_GS, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(SFM_MAZE_GOSSIP_STONE_LOWER, {[]{return true;}}),
LocationAccess(SFM_MAZE_GOSSIP_STONE_UPPER, {[]{return true;}}),
LocationAccess(SFM_SARIA_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_SONG_FROM_SARIA, {[]{return IsChild && ZeldasLetter;}}),
LocationAccess(RC_SHEIK_IN_FOREST, {[]{return IsAdult;}}),
LocationAccess(RC_SFM_GS, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_SFM_MAZE_LOWER_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_SFM_MAZE_UPPER_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_SFM_SARIA_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(SFM_ENTRYWAY, {[]{return true;}}),
Entrance(FOREST_TEMPLE_ENTRYWAY, {[]{return CanUse(HOOKSHOT);}}),
Entrance(SFM_FAIRY_GROTTO, {[]{return true;}}),
Entrance(SFM_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
Entrance(RR_SFM_ENTRYWAY, {[]{return true;}}),
Entrance(RR_FOREST_TEMPLE_ENTRYWAY, {[]{return CanUse(RG_HOOKSHOT);}}),
Entrance(RR_SFM_FAIRY_GROTTO, {[]{return true;}}),
Entrance(RR_SFM_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
});
areaTable[SFM_FAIRY_GROTTO] = Area("SFM Fairy Grotto", "SFM Fairy Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_SFM_FAIRY_GROTTO] = Area("SFM Fairy Grotto", "SFM Fairy Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FreeFairies, {[]{return true;}}),
}, {}, {
//Exits
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
Entrance(RR_SACRED_FOREST_MEADOW, {[]{return true;}}),
});
areaTable[SFM_WOLFOS_GROTTO] = Area("SFM Wolfos Grotto", "SFM Wolfos Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SFM_WOLFOS_GROTTO] = Area("SFM Wolfos Grotto", "SFM Wolfos Grotto", RHT_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);}}),
LocationAccess(RC_SFM_WOLFOS_GROTTO_CHEST, {[]{return IsAdult || Slingshot || Sticks || KokiriSword || CanUse(RG_DINS_FIRE) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
}, {
//Exits
Entrance(SFM_ENTRYWAY, {[]{return true;}}),
Entrance(RR_SFM_ENTRYWAY, {[]{return true;}}),
});
areaTable[SFM_STORMS_GROTTO] = Area("SFM Storms Grotto", "SFM Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SFM_STORMS_GROTTO] = Area("SFM Storms Grotto", "SFM Storms Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SFM_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(SFM_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
LocationAccess(RC_SFM_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(RC_SFM_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
Entrance(RR_SACRED_FOREST_MEADOW, {[]{return true;}}),
});
areaTable[LW_BRIDGE_FROM_FOREST] = Area("LW Bridge From Forest", "Lost Woods", THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_LW_BRIDGE_FROM_FOREST] = Area("LW Bridge From Forest", "Lost Woods", RHT_THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(LW_GIFT_FROM_SARIA, {[]{return true;}}),
LocationAccess(RC_LW_GIFT_FROM_SARIA, {[]{return true;}}),
}, {
//Exits
Entrance(LW_BRIDGE, {[]{return true;}}),
Entrance(RR_LW_BRIDGE, {[]{return true;}}),
});
areaTable[LW_BRIDGE] = Area("LW Bridge", "Lost Woods", THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_LW_BRIDGE] = Area("LW Bridge", "Lost Woods", RHT_THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(KOKIRI_FOREST, {[]{return true;}}),
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(THE_LOST_WOODS, {[]{return CanUse(LONGSHOT);}}),
Entrance(RR_KOKIRI_FOREST, {[]{return true;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_THE_LOST_WOODS, {[]{return CanUse(RG_LONGSHOT);}}),
});
}

View File

@@ -10,81 +10,81 @@ void AreaTable_Init_ShadowTemple() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[SHADOW_TEMPLE_ENTRYWAY] = Area("Shadow Temple Entryway", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SHADOW_TEMPLE_ENTRYWAY] = Area("Shadow Temple Entryway", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(SHADOW_TEMPLE_BEGINNING, {[]{return Dungeon::ShadowTemple.IsVanilla() && (LogicLensShadow || CanUse(LENS_OF_TRUTH)) && (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT));}}),
Entrance(SHADOW_TEMPLE_MQ_BEGINNING, {[]{return Dungeon::ShadowTemple.IsMQ() && (LogicLensShadowMQ || CanUse(LENS_OF_TRUTH)) && (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT));}}),
Entrance(GRAVEYARD_WARP_PAD_REGION, {[]{return true;}}),
Entrance(RR_SHADOW_TEMPLE_BEGINNING, {[]{return Dungeon::ShadowTemple.IsVanilla() && (LogicLensShadow || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
Entrance(RR_SHADOW_TEMPLE_MQ_BEGINNING, {[]{return Dungeon::ShadowTemple.IsMQ() && (LogicLensShadowMQ || CanUse(RG_LENS_OF_TRUTH)) && (CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
Entrance(RR_GRAVEYARD_WARP_PAD_REGION, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::ShadowTemple.IsVanilla()) {
areaTable[SHADOW_TEMPLE_BEGINNING] = Area("Shadow Temple Beginning", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_SHADOW_TEMPLE_BEGINNING] = Area("Shadow Temple Beginning", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&NutPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(SHADOW_TEMPLE_MAP_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_HOVER_BOOTS_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MAP_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_HOVER_BOOTS_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(SHADOW_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(SHADOW_TEMPLE_FIRST_BEAMOS, {[]{return HoverBoots;}}),
Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_SHADOW_TEMPLE_FIRST_BEAMOS, {[]{return HoverBoots;}}),
});
areaTable[SHADOW_TEMPLE_FIRST_BEAMOS] = Area("Shadow Temple First Beamos", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_SHADOW_TEMPLE_FIRST_BEAMOS] = Area("Shadow Temple First Beamos", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}), //This fairy pot is only on 3DS
}, {
//Locations
LocationAccess(SHADOW_TEMPLE_COMPASS_CHEST, {[]{return IsAdult || KokiriSword || Sticks;}}),
LocationAccess(SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, {[]{return CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT);}}),
LocationAccess(SHADOW_TEMPLE_GS_NEAR_SHIP, {[]{return false;}}),
LocationAccess(RC_SHADOW_TEMPLE_COMPASS_CHEST, {[]{return IsAdult || KokiriSword || Sticks;}}),
LocationAccess(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, {[]{return CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT);}}),
LocationAccess(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, {[]{return false;}}),
}, {
//Exits
Entrance(SHADOW_TEMPLE_HUGE_PIT, {[]{return HasExplosives && IsAdult && SmallKeys(SHADOW_TEMPLE, 1, 2);}}),
Entrance(SHADOW_TEMPLE_BEYOND_BOAT, {[]{return false;}}),
Entrance(RR_SHADOW_TEMPLE_HUGE_PIT, {[]{return HasExplosives && IsAdult && SmallKeys(RR_SHADOW_TEMPLE, 1, 2);}}),
Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, {[]{return false;}}),
});
areaTable[SHADOW_TEMPLE_HUGE_PIT] = Area("Shadow Temple Huge Pit", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SHADOW_TEMPLE_HUGE_PIT] = Area("Shadow Temple Huge Pit", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
LocationAccess(SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
LocationAccess(SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, {[]{return SmallKeys(SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(LENS_OF_TRUTH));}}),
LocationAccess(SHADOW_TEMPLE_FREESTANDING_KEY, {[]{return SmallKeys(SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(LENS_OF_TRUTH)) && Hookshot && (Bombs || GoronBracelet || (LogicShadowFreestandingKey && HasBombchus));}}),
LocationAccess(SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (LogicShadowUmbrellaGS && HoverBoots);}}),
LocationAccess(SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, {[]{return SmallKeys(SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(LENS_OF_TRUTH)) && Hookshot;}}),
LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
LocationAccess(RC_SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_SHADOW_TEMPLE_FREESTANDING_KEY, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && (Bombs || GoronBracelet || (LogicShadowFreestandingKey && HasBombchus));}}),
LocationAccess(RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (LogicShadowUmbrellaGS && HoverBoots);}}),
LocationAccess(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, {[]{return SmallKeys(RR_SHADOW_TEMPLE, 2, 3) && ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot;}}),
}, {
//Exits
Entrance(SHADOW_TEMPLE_WIND_TUNNEL, {[]{return ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(LENS_OF_TRUTH)) && Hookshot && SmallKeys(SHADOW_TEMPLE, 3, 4);}}),
Entrance(RR_SHADOW_TEMPLE_WIND_TUNNEL, {[]{return ((LogicLensShadowPlatform && LogicLensShadow) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && SmallKeys(RR_SHADOW_TEMPLE, 3, 4);}}),
});
areaTable[SHADOW_TEMPLE_WIND_TUNNEL] = Area("Shadow Temple Wind Tunnel", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SHADOW_TEMPLE_WIND_TUNNEL] = Area("Shadow Temple Wind Tunnel", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHADOW_TEMPLE_WIND_HINT_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_GS_NEAR_SHIP, {[]{return CanUse(LONGSHOT) && SmallKeys(SHADOW_TEMPLE, 4, 5);}}),
LocationAccess(RC_SHADOW_TEMPLE_WIND_HINT_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_GS_NEAR_SHIP, {[]{return CanUse(RG_LONGSHOT) && SmallKeys(RR_SHADOW_TEMPLE, 4, 5);}}),
}, {
//Exits
Entrance(SHADOW_TEMPLE_BEYOND_BOAT, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(SHADOW_TEMPLE, 4, 5);}}),
Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(RR_SHADOW_TEMPLE, 4, 5);}}),
});
areaTable[SHADOW_TEMPLE_BEYOND_BOAT] = Area("Shadow Temple Beyond Boat", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SHADOW_TEMPLE_BEYOND_BOAT] = Area("Shadow Temple Beyond Boat", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, {[]{return CanUse(DINS_FIRE);}}),
LocationAccess(SHADOW_TEMPLE_BOSS_KEY_CHEST, {[]{return CanUse(DINS_FIRE);}}),
LocationAccess(SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST, {[]{return CanUse(RG_DINS_FIRE);}}),
LocationAccess(RC_SHADOW_TEMPLE_BOSS_KEY_CHEST, {[]{return CanUse(RG_DINS_FIRE);}}),
LocationAccess(RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, {[]{return true;}}),
}, {
//Exits
Entrance(SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(BOW) || CanUse(DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus)) && SmallKeys(SHADOW_TEMPLE, 5) && CanUse(HOVER_BOOTS) && BossKeyShadowTemple;}})
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || CanUse(RG_DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus)) && SmallKeys(RR_SHADOW_TEMPLE, 5) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}})
});
}
@@ -92,121 +92,121 @@ void AreaTable_Init_ShadowTemple() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::ShadowTemple.IsMQ()) {
areaTable[SHADOW_TEMPLE_MQ_BEGINNING] = Area("Shadow Temple MQ Beginning", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SHADOW_TEMPLE_MQ_BEGINNING] = Area("Shadow Temple MQ Beginning", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(SHADOW_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(SHADOW_TEMPLE_MQ_FIRST_BEAMOS, {[]{return IsAdult && (CanUse(FIRE_ARROWS) || HoverBoots || (LogicShadowMQGap && CanUse(LONGSHOT)));}}),
//Trick: IsAdult && (CanUse(FIRE_ARROWS) || HoverBoots || (LogicShadowMQGap && CanUse(LONGSHOT)))
Entrance(SHADOW_TEMPLE_MQ_DEAD_HAND_AREA, {[]{return HasExplosives && SmallKeys(SHADOW_TEMPLE, 6);}}),
Entrance(RR_SHADOW_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, {[]{return IsAdult && (CanUse(RG_FIRE_ARROWS) || HoverBoots || (LogicShadowMQGap && CanUse(RG_LONGSHOT)));}}),
//Trick: IsAdult && (CanUse(RG_FIRE_ARROWS) || HoverBoots || (LogicShadowMQGap && CanUse(RG_LONGSHOT)))
Entrance(RR_SHADOW_TEMPLE_MQ_DEAD_HAND_AREA, {[]{return HasExplosives && SmallKeys(RR_SHADOW_TEMPLE, 6);}}),
});
areaTable[SHADOW_TEMPLE_MQ_DEAD_HAND_AREA] = Area("Shadow Temple MQ Dead Hand Area", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SHADOW_TEMPLE_MQ_DEAD_HAND_AREA] = Area("Shadow Temple MQ Dead Hand Area", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHADOW_TEMPLE_MQ_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, {[]{return CanPlay(SongOfTime) && IsAdult && CanUse(BOW);}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_COMPASS_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, {[]{return CanPlay(SongOfTime) && IsAdult && CanUse(RG_FAIRY_BOW);}}),
}, {});
areaTable[SHADOW_TEMPLE_MQ_FIRST_BEAMOS] = Area("Shadow Temple MQ First Beamos", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS] = Area("Shadow Temple MQ First Beamos", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHADOW_TEMPLE_MQ_MAP_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, {[]{return HasExplosives && SmallKeys(SHADOW_TEMPLE, 2);}}),
Entrance(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, {[]{return HasExplosives && SmallKeys(RR_SHADOW_TEMPLE, 2);}}),
});
areaTable[SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT] = Area("Shadow Temple MQ Upper Huge Pit", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT] = Area("Shadow Temple MQ Upper Huge Pit", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO));}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO));}}),
//Trick: CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
LocationAccess(SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO));}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO));}}),
//Trick: CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
}, {
//Exits
Entrance(SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, {[]{return HasFireSource || LogicShadowMQHugePit;}}),
Entrance(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, {[]{return HasFireSource || LogicShadowMQHugePit;}}),
//Trick: HasFireSource || LogicShadowMQHugePit
});
areaTable[SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT] = Area("Shadow Temple MQ Lower Huge Pit", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT] = Area("Shadow Temple MQ Lower Huge Pit", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, {[]{return IsAdult && CanUse(LONGSHOT);}}),
LocationAccess(SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
LocationAccess(SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
LocationAccess(SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, {[]{return HoverBoots && SmallKeys(SHADOW_TEMPLE, 3) && ((LogicLensShadowMQ && LogicLensShadowMQPlatform) || CanUse(LENS_OF_TRUTH));}}),
LocationAccess(SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, {[]{return HoverBoots && SmallKeys(SHADOW_TEMPLE, 3) && Hookshot && ((LogicLensShadowMQ && LogicLensShadowMQInvisibleBlades && LogicLensShadowMQPlatform) || CanUse(LENS_OF_TRUTH));}}),
LocationAccess(SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (LogicShadowUmbrellaGS && HoverBoots);}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, {[]{return IsAdult && CanUse(RG_LONGSHOT);}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST, {[]{return (LogicShadowUmbrella && HoverBoots) || GoronBracelet;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, {[]{return HoverBoots && SmallKeys(RR_SHADOW_TEMPLE, 3) && ((LogicLensShadowMQ && LogicLensShadowMQPlatform) || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, {[]{return HoverBoots && SmallKeys(RR_SHADOW_TEMPLE, 3) && Hookshot && ((LogicLensShadowMQ && LogicLensShadowMQInvisibleBlades && LogicLensShadowMQPlatform) || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot || (LogicShadowUmbrellaGS && HoverBoots);}}),
}, {
//Exits
Entrance(SHADOW_TEMPLE_MQ_WIND_TUNNEL, {[]{return HoverBoots && ((LogicLensShadowMQ && LogicLensShadowMQPlatform) || CanUse(LENS_OF_TRUTH)) && Hookshot && SmallKeys(SHADOW_TEMPLE, 4);}}),
Entrance(RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL, {[]{return HoverBoots && ((LogicLensShadowMQ && LogicLensShadowMQPlatform) || CanUse(RG_LENS_OF_TRUTH)) && Hookshot && SmallKeys(RR_SHADOW_TEMPLE, 4);}}),
});
areaTable[SHADOW_TEMPLE_MQ_WIND_TUNNEL] = Area("Shadow Temple MQ Wind Tunnel", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_SHADOW_TEMPLE_MQ_WIND_TUNNEL] = Area("Shadow Temple MQ Wind Tunnel", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&NutPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_MQ_GS_AFTER_WIND, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_WIND_HINT_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_AFTER_WIND, {[]{return true;}}),
}, {
//Exits
Entrance(SHADOW_TEMPLE_MQ_BEYOND_BOAT, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(SHADOW_TEMPLE, 5);}}),
Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(RR_SHADOW_TEMPLE, 5);}}),
});
areaTable[SHADOW_TEMPLE_MQ_BEYOND_BOAT] = Area("Shadow Temple MQ Beyond Boat", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT] = Area("Shadow Temple MQ Beyond Boat", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, {[]{return true;}}),
LocationAccess(SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, {[]{return Bow || (LogicShadowStatue && HasBombchus);}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, {[]{return Bow || (LogicShadowStatue && HasBombchus);}}),
}, {
//Exits
Entrance(SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, {[]{return Bow && CanPlay(SongOfTime) && IsAdult && CanUse(LONGSHOT);}}),
Entrance(SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(BOW) || (LogicShadowStatue && HasBombchus)) && CanUse(HOVER_BOOTS) && BossKeyShadowTemple;}}),
Entrance(RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, {[]{return Bow && CanPlay(SongOfTime) && IsAdult && CanUse(RG_LONGSHOT);}}),
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, {[]{return (CanUse(RG_FAIRY_BOW) || (LogicShadowStatue && HasBombchus)) && CanUse(RG_HOVER_BOOTS) && BossKeyShadowTemple;}}),
});
areaTable[SHADOW_TEMPLE_MQ_INVISIBLE_MAZE] = Area("Shadow Temple MQ Invisible Maze", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SHADOW_TEMPLE_MQ_INVISIBLE_MAZE] = Area("Shadow Temple MQ Invisible Maze", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, {[]{return CanUse(DINS_FIRE) && SmallKeys(SHADOW_TEMPLE, 6);}}),
LocationAccess(SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return CanUse(DINS_FIRE) && SmallKeys(SHADOW_TEMPLE, 6);}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST, {[]{return CanUse(RG_DINS_FIRE) && SmallKeys(RR_SHADOW_TEMPLE, 6);}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return CanUse(RG_DINS_FIRE) && SmallKeys(RR_SHADOW_TEMPLE, 6);}}),
//below previously returned true
LocationAccess(SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, {[]{return CanUse(LENS_OF_TRUTH) || LogicLensShadowMQDeadHand;}}),
LocationAccess(SHADOW_TEMPLE_MQ_FREESTANDING_KEY, {[]{return true;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, {[]{return CanUse(RG_LENS_OF_TRUTH) || LogicLensShadowMQDeadHand;}}),
LocationAccess(RC_SHADOW_TEMPLE_MQ_FREESTANDING_KEY, {[]{return true;}}),
}, {});
}
/*---------------------------
| BOSS ROOM |
---------------------------*/
areaTable[SHADOW_TEMPLE_BOSS_ENTRYWAY] =
Area("Shadow Temple Boss Entryway", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_SHADOW_TEMPLE_BOSS_ENTRYWAY] =
Area("Shadow Temple Boss Entryway", "Shadow Temple", RHT_SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(SHADOW_TEMPLE_BEYOND_BOAT, { [] { return Dungeon::ShadowTemple.IsVanilla() && false; } }),
Entrance(SHADOW_TEMPLE_MQ_BEYOND_BOAT, { [] { return Dungeon::ShadowTemple.IsMQ() && false; } }),
Entrance(SHADOW_TEMPLE_BOSS_ROOM, { [] { return true; } }),
Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, { [] { return Dungeon::ShadowTemple.IsVanilla() && false; } }),
Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, { [] { return Dungeon::ShadowTemple.IsMQ() && false; } }),
Entrance(RR_SHADOW_TEMPLE_BOSS_ROOM, { [] { return true; } }),
});
areaTable[SHADOW_TEMPLE_BOSS_ROOM] =
Area("Shadow Temple Boss Room", "Shadow Temple", NONE, NO_DAY_NIGHT_CYCLE,
areaTable[RR_SHADOW_TEMPLE_BOSS_ROOM] =
Area("Shadow Temple Boss Room", "Shadow Temple", RHT_NONE, NO_DAY_NIGHT_CYCLE,
{
// Events
EventAccess(&ShadowTempleClear, { [] {
return ShadowTempleClear || (HasBossSoul(BONGO_BONGO_BOSS_SOUL) &&
((CanUse(LENS_OF_TRUTH) || LogicLensBongo) &&
(CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) &&
(CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT) || LogicShadowBongo)));
return ShadowTempleClear || (HasBossSoul(RG_BONGO_BONGO_SOUL) &&
((CanUse(RG_LENS_OF_TRUTH) || LogicLensBongo) &&
(CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) &&
(CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) || LogicShadowBongo)));
} }),
},
{
// Locations
LocationAccess(SHADOW_TEMPLE_BONGO_BONGO_HEART, { [] { return ShadowTempleClear; } }),
LocationAccess(BONGO_BONGO, { [] { return ShadowTempleClear; } }),
LocationAccess(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, { [] { return ShadowTempleClear; } }),
LocationAccess(RC_BONGO_BONGO, { [] { return ShadowTempleClear; } }),
},
{
// Exits
Entrance(SHADOW_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
});
}

View File

@@ -10,133 +10,133 @@ void AreaTable_Init_SpiritTemple() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[SPIRIT_TEMPLE_ENTRYWAY] = Area("Spirit Temple Entryway", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SPIRIT_TEMPLE_ENTRYWAY] = Area("Spirit Temple Entryway", "Spirit Temple", RHT_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_FROM_SPIRIT_ENTRYWAY, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_LOBBY, {[]{return Dungeon::SpiritTemple.IsVanilla();}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, {[]{return Dungeon::SpiritTemple.IsMQ();}}),
Entrance(RR_DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, {[]{return true;}}),
});
/*--------------------------
| VANILLA DUNGEON |
---------------------------*/
if (Dungeon::SpiritTemple.IsVanilla()) {
areaTable[SPIRIT_TEMPLE_LOBBY] = Area("Spirit Temple Lobby", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SPIRIT_TEMPLE_LOBBY] = Area("Spirit Temple Lobby", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(SPIRIT_TEMPLE_CHILD, {[]{return IsChild;}}),
Entrance(SPIRIT_TEMPLE_EARLY_ADULT, {[]{return CanUse(SILVER_GAUNTLETS);}}),
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_CHILD, {[]{return IsChild;}}),
Entrance(RR_SPIRIT_TEMPLE_EARLY_ADULT, {[]{return CanUse(RG_SILVER_GAUNTLETS);}}),
});
areaTable[SPIRIT_TEMPLE_CHILD] = Area("Child Spirit Temple", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_SPIRIT_TEMPLE_CHILD] = Area("Child Spirit Temple", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&NutCrate, {[]{return true;}}),
}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}),
LocationAccess(SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot))) && (Sticks || CanUse(DINS_FIRE));}}),
LocationAccess(SPIRIT_TEMPLE_GS_METAL_FENCE, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}),
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}),
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot))) && (Sticks || CanUse(RG_DINS_FIRE));}}),
LocationAccess(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, {[]{return (Boomerang || Slingshot || (HasBombchus && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}),
}, {
//Exits
Entrance(SPIRIT_TEMPLE_CHILD_CLIMB, {[]{return SmallKeys(SPIRIT_TEMPLE, 1);}}),
Entrance(RR_SPIRIT_TEMPLE_CHILD_CLIMB, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 1);}}),
});
areaTable[SPIRIT_TEMPLE_CHILD_CLIMB] = Area("Child Spirit Temple Climb", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Area("Child Spirit Temple Climb", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(SPIRIT_TEMPLE, 3) || (SmallKeys(SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}),
LocationAccess(SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(SPIRIT_TEMPLE, 3) || (SmallKeys(SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}),
LocationAccess(SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, {[]{return HasProjectile(HasProjectileAge::Both) || CanUse(DINS_FIRE) ||
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}),
LocationAccess(RC_SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST, {[]{return HasProjectile(HasProjectileAge::Both) || ((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && HasProjectile(HasProjectileAge::Adult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 5) && IsChild && HasProjectile(HasProjectileAge::Child));}}),
LocationAccess(RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM, {[]{return HasProjectile(HasProjectileAge::Both) || CanUse(RG_DINS_FIRE) ||
(CanTakeDamage && (Sticks || KokiriSword || HasProjectile(HasProjectileAge::Child))) ||
(IsChild && SmallKeys(SPIRIT_TEMPLE, 5) && HasProjectile(HasProjectileAge::Child)) ||
((SmallKeys(SPIRIT_TEMPLE, 3) || (SmallKeys(SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(SILVER_GAUNTLETS) && (HasProjectile(HasProjectileAge::Adult) || CanTakeDamage));}}),
(IsChild && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasProjectile(HasProjectileAge::Child)) ||
((SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) && CanUse(RG_SILVER_GAUNTLETS) && (HasProjectile(HasProjectileAge::Adult) || CanTakeDamage));}}),
}, {
//Exits
Entrance(SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return HasExplosives || (SunlightArrows && CanUse(LIGHT_ARROWS));}}),
Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return HasExplosives || (SunlightArrows && CanUse(RG_LIGHT_ARROWS));}}),
});
areaTable[SPIRIT_TEMPLE_EARLY_ADULT] = Area("Early Adult Spirit Temple", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_EARLY_ADULT] = Area("Early Adult Spirit Temple", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_COMPASS_CHEST, {[]{return CanUse(HOOKSHOT) && CanPlay(ZeldasLullaby);}}),
LocationAccess(SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, {[]{return Bow || Hookshot || HasBombchus || (Bombs && LogicSpiritLowerAdultSwitch);}}),
LocationAccess(SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 3);}}),
LocationAccess(SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 3);}}),
LocationAccess(SPIRIT_TEMPLE_GS_BOULDER_ROOM, {[]{return CanPlay(SongOfTime) && (Bow || Hookshot || HasBombchus || (Bombs && LogicSpiritLowerAdultSwitch));}}),
LocationAccess(RC_SPIRIT_TEMPLE_COMPASS_CHEST, {[]{return CanUse(RG_HOOKSHOT) && CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST, {[]{return Bow || Hookshot || HasBombchus || (Bombs && LogicSpiritLowerAdultSwitch);}}),
LocationAccess(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3);}}),
LocationAccess(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3);}}),
LocationAccess(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, {[]{return CanPlay(SongOfTime) && (Bow || Hookshot || HasBombchus || (Bombs && LogicSpiritLowerAdultSwitch));}}),
}, {
//Exits
Entrance(SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return SmallKeys(SPIRIT_TEMPLE, 1);}}),
Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 1);}}),
});
areaTable[SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Area("Spirit Temple Central Chamber", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Area("Spirit Temple Central Chamber", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_MAP_CHEST, {[]{return ((HasExplosives || SmallKeys(SPIRIT_TEMPLE, 3) || (SmallKeys(SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) &&
LocationAccess(RC_SPIRIT_TEMPLE_MAP_CHEST, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) &&
(CanUse(DINS_FIRE) ||
(CanUse(RG_DINS_FIRE) ||
(((MagicMeter && FireArrows) || LogicSpiritMapChest) && Bow && Sticks))) ||
(SmallKeys(SPIRIT_TEMPLE, 5) && HasExplosives &&
CanUse(STICKS)) ||
(SmallKeys(SPIRIT_TEMPLE, 3) &&
(CanUse(FIRE_ARROWS) || (LogicSpiritMapChest && Bow)) &&
CanUse(SILVER_GAUNTLETS));}}),
LocationAccess(SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, {[]{return ((HasExplosives || SmallKeys(SPIRIT_TEMPLE, 3) || (SmallKeys(SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) &&
(CanUse(DINS_FIRE) ||
(SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives &&
CanUse(RG_STICKS)) ||
(SmallKeys(RR_SPIRIT_TEMPLE, 3) &&
(CanUse(RG_FIRE_ARROWS) || (LogicSpiritMapChest && Bow)) &&
CanUse(RG_SILVER_GAUNTLETS));}}),
LocationAccess(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) &&
(CanUse(RG_DINS_FIRE) ||
(((MagicMeter && FireArrows) || LogicSpiritSunChest) && Bow && Sticks))) ||
(SmallKeys(SPIRIT_TEMPLE, 5) && HasExplosives &&
CanUse(STICKS)) ||
(SmallKeys(SPIRIT_TEMPLE, 3) &&
(CanUse(FIRE_ARROWS) || (LogicSpiritSunChest && Bow)) &&
CanUse(SILVER_GAUNTLETS));}}),
LocationAccess(SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 3) && CanUse(SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby);}}),
LocationAccess(SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 3) && CanUse(SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby) && (Hookshot || HoverBoots || LogicSpiritLobbyJump);}}),
LocationAccess(SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, {[]{return (HasExplosives && Boomerang && Hookshot) ||
(CanUse(BOOMERANG) && SmallKeys(SPIRIT_TEMPLE, 5) && HasExplosives) ||
(Hookshot && CanUse(SILVER_GAUNTLETS) &&
(SmallKeys(SPIRIT_TEMPLE, 3) ||
(SmallKeys(SPIRIT_TEMPLE, 2) && Boomerang && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))));}}),
LocationAccess(SPIRIT_TEMPLE_GS_LOBBY, {[]{return ((HasExplosives || SmallKeys(SPIRIT_TEMPLE, 3) || (SmallKeys(SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) &&
(SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives &&
CanUse(RG_STICKS)) ||
(SmallKeys(RR_SPIRIT_TEMPLE, 3) &&
(CanUse(RG_FIRE_ARROWS) || (LogicSpiritSunChest && Bow)) &&
CanUse(RG_SILVER_GAUNTLETS));}}),
LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && CanPlay(ZeldasLullaby) && (Hookshot || HoverBoots || LogicSpiritLobbyJump);}}),
LocationAccess(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, {[]{return (HasExplosives && Boomerang && Hookshot) ||
(CanUse(RG_BOOMERANG) && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives) ||
(Hookshot && CanUse(RG_SILVER_GAUNTLETS) &&
(SmallKeys(RR_SPIRIT_TEMPLE, 3) ||
(SmallKeys(RR_SPIRIT_TEMPLE, 2) && Boomerang && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))));}}),
LocationAccess(RC_SPIRIT_TEMPLE_GS_LOBBY, {[]{return ((HasExplosives || SmallKeys(RR_SPIRIT_TEMPLE, 3) || (SmallKeys(RR_SPIRIT_TEMPLE, 2) && BombchusInLogic && ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_OFF))) &&
LogicSpiritLobbyGS && Boomerang && (Hookshot || HoverBoots || LogicSpiritLobbyJump)) ||
(LogicSpiritLobbyGS && SmallKeys(SPIRIT_TEMPLE, 5) && HasExplosives && CanUse(BOOMERANG)) ||
(SmallKeys(SPIRIT_TEMPLE, 3) && CanUse(SILVER_GAUNTLETS) && (Hookshot || HoverBoots || LogicSpiritLobbyJump));}}),
(LogicSpiritLobbyGS && SmallKeys(RR_SPIRIT_TEMPLE, 5) && HasExplosives && CanUse(RG_BOOMERANG)) ||
(SmallKeys(RR_SPIRIT_TEMPLE, 3) && CanUse(RG_SILVER_GAUNTLETS) && (Hookshot || HoverBoots || LogicSpiritLobbyJump));}}),
}, {
//Exits
Entrance(SPIRIT_TEMPLE_OUTDOOR_HANDS, {[]{return true;}}),
Entrance(SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR, {[]{return SmallKeys(SPIRIT_TEMPLE, 4) && CanUse(SILVER_GAUNTLETS);}}),
Entrance(SPIRIT_TEMPLE_CHILD_CLIMB, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_OUTDOOR_HANDS, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanUse(RG_SILVER_GAUNTLETS);}}),
Entrance(RR_SPIRIT_TEMPLE_CHILD_CLIMB, {[]{return true;}}),
});
areaTable[SPIRIT_TEMPLE_OUTDOOR_HANDS] = Area("Spirit Temple Outdoor Hands", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_OUTDOOR_HANDS] = Area("Spirit Temple Outdoor Hands", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, {[]{return (SmallKeys(SPIRIT_TEMPLE, 3) && Longshot && HasExplosives) || SmallKeys(SPIRIT_TEMPLE, 5);}}),
LocationAccess(SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 4) && CanUse(SILVER_GAUNTLETS) && HasExplosives;}}),
LocationAccess(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 3) && Longshot && HasExplosives) || SmallKeys(RR_SPIRIT_TEMPLE, 5);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanUse(RG_SILVER_GAUNTLETS) && HasExplosives;}}),
}, {
//Exits
Entrance(DESERT_COLOSSUS, {[]{return (IsChild && SmallKeys(SPIRIT_TEMPLE, 5)) || (CanUse(SILVER_GAUNTLETS) && ((SmallKeys(SPIRIT_TEMPLE, 3) && HasExplosives) || SmallKeys(SPIRIT_TEMPLE, 5)));}}),
Entrance(RR_DESERT_COLOSSUS, {[]{return (IsChild && SmallKeys(RR_SPIRIT_TEMPLE, 5)) || (CanUse(RG_SILVER_GAUNTLETS) && ((SmallKeys(RR_SPIRIT_TEMPLE, 3) && HasExplosives) || SmallKeys(RR_SPIRIT_TEMPLE, 5)));}}),
});
areaTable[SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Central Locked Door", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Central Locked Door", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, {[]{return (MirrorShield || (SunlightArrows && CanUse(LIGHT_ARROWS))) && HasExplosives;}}),
LocationAccess(SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, {[]{return (LogicLensSpirit || CanUse(LENS_OF_TRUTH)) && HasExplosives;}}),
LocationAccess(SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, {[]{return (LogicLensSpirit || CanUse(LENS_OF_TRUTH)) && HasExplosives;}}),
LocationAccess(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, {[]{return (MirrorShield || (SunlightArrows && CanUse(RG_LIGHT_ARROWS))) && HasExplosives;}}),
LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST, {[]{return (LogicLensSpirit || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}),
LocationAccess(RC_SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST, {[]{return (LogicLensSpirit || CanUse(RG_LENS_OF_TRUTH)) && HasExplosives;}}),
}, {
//Exits
Entrance(SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, {[]{return SmallKeys(SPIRIT_TEMPLE, 5) && (LogicSpiritWall || CanUse(LONGSHOT) || HasBombchus || ((Bombs || Nuts || CanUse(DINS_FIRE)) && (Bow || CanUse(HOOKSHOT) || Hammer)));}}),
Entrance(RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && (LogicSpiritWall || CanUse(RG_LONGSHOT) || HasBombchus || ((Bombs || Nuts || CanUse(RG_DINS_FIRE)) && (Bow || CanUse(RG_HOOKSHOT) || Hammer)));}}),
});
areaTable[SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Final Locked Door", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Final Locked Door", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return CanPlay(ZeldasLullaby) && ((CanTakeDamage && LogicFlamingChests) || (Bow && Hookshot));}}),
LocationAccess(SPIRIT_TEMPLE_TOPMOST_CHEST, {[]{return MirrorShield || (SunlightArrows && CanUse(LIGHT_ARROWS));}}),
LocationAccess(RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return CanPlay(ZeldasLullaby) && ((CanTakeDamage && LogicFlamingChests) || (Bow && Hookshot));}}),
LocationAccess(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, {[]{return MirrorShield || (SunlightArrows && CanUse(RG_LIGHT_ARROWS));}}),
}, {
//Exits
Entrance(SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, {[]{return MirrorShield && HasExplosives && Hookshot;}}),
Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, {[]{return MirrorShield && HasExplosives && Hookshot;}}),
});
areaTable[SPIRIT_TEMPLE_INSIDE_STATUE_HEAD] =
Area("Spirit Temple Inside Statue Head", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD] =
Area("Spirit Temple Inside Statue Head", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(SPIRIT_TEMPLE_CENTRAL_CHAMBER, { [] { return true; } }),
Entrance(SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return BossKeySpiritTemple; } }),
Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, { [] { return true; } }),
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return BossKeySpiritTemple; } }),
});
}
@@ -144,132 +144,132 @@ void AreaTable_Init_SpiritTemple() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::SpiritTemple.IsMQ()) {
areaTable[SPIRIT_TEMPLE_MQ_LOBBY] = Area("Spirit Temple MQ Lobby", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_LOBBY] = Area("Spirit Temple MQ Lobby", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, {[]{return true;}}),
LocationAccess(SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, {[]{return Here(SPIRIT_TEMPLE_MQ_LOBBY, []{return CanBlastOrSmash;}) && ((IsChild && CanUse(SLINGSHOT)) || (IsAdult && CanUse(BOW)));}}),
LocationAccess(SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, {[]{return HasBombchus || (IsAdult && (CanUse(BOW) || CanUse(HOOKSHOT))) || (IsChild && (CanUse(SLINGSHOT) || CanUse(BOOMERANG)));}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST, {[]{return true;}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return CanBlastOrSmash;}) && ((IsChild && CanUse(RG_FAIRY_SLINGSHOT)) || (IsAdult && CanUse(RG_FAIRY_BOW)));}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, {[]{return HasBombchus || (IsAdult && (CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT))) || (IsChild && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG)));}}),
}, {
//Exits
Entrance(SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(SPIRIT_TEMPLE_MQ_CHILD, {[]{return IsChild;}}),
Entrance(SPIRIT_TEMPLE_MQ_ADULT, {[]{return HasBombchus && IsAdult && CanUse(LONGSHOT) && CanUse(SILVER_GAUNTLETS);}}),
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_CHILD, {[]{return IsChild;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_ADULT, {[]{return HasBombchus && IsAdult && CanUse(RG_LONGSHOT) && CanUse(RG_SILVER_GAUNTLETS);}}),
});
areaTable[SPIRIT_TEMPLE_MQ_CHILD] = Area("Spirit Temple MQ Child", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_SPIRIT_TEMPLE_MQ_CHILD] = Area("Spirit Temple MQ Child", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return FairyPot || (KokiriSword && HasBombchus && Slingshot);}}),
}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, {[]{return Here(SPIRIT_TEMPLE_MQ_ADULT, []{return SmallKeys(SPIRIT_TEMPLE, 7) && Hammer;});}}),
LocationAccess(SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, {[]{return KokiriSword && HasBombchus && Slingshot && CanUse(DINS_FIRE);}}),
LocationAccess(SPIRIT_TEMPLE_MQ_MAP_CHEST, {[]{return KokiriSword || Bombs;}}),
LocationAccess(SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, {[]{return HasBombchus && SmallKeys(SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(DINS_FIRE) || (Here(SPIRIT_TEMPLE_MQ_ADULT, []{return IsAdult && (CanUse(FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(BOW) && CanPlay(SongOfTime)));})));}}),
//Trick: HasBombchus && SmallKeys(SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(DINS_FIRE) || (SPIRIT_TEMPLE_MQ_ADULT.Adult() && IsAdult && (CanUse(FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(BOW) && CanPlay(SongOfTime)))))
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST, {[]{return Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return SmallKeys(RR_SPIRIT_TEMPLE, 7) && Hammer;});}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, {[]{return KokiriSword && HasBombchus && Slingshot && CanUse(RG_DINS_FIRE);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_MAP_CHEST, {[]{return KokiriSword || Bombs;}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, {[]{return HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (Here(RR_SPIRIT_TEMPLE_MQ_ADULT, []{return IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(RG_FAIRY_BOW) && CanPlay(SongOfTime)));})));}}),
//Trick: HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(RG_DINS_FIRE) || (SPIRIT_TEMPLE_MQ_ADULT.Adult() && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(RG_FAIRY_BOW) && CanPlay(SongOfTime)))))
}, {
//Exits
Entrance(SPIRIT_TEMPLE_MQ_SHARED, {[]{return HasBombchus && SmallKeys(SPIRIT_TEMPLE, 2);}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SHARED, {[]{return HasBombchus && SmallKeys(RR_SPIRIT_TEMPLE, 2);}}),
});
areaTable[SPIRIT_TEMPLE_MQ_ADULT] = Area("Spirit Temple MQ Adult", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_ADULT] = Area("Spirit Temple MQ Adult", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 7);}}),
LocationAccess(SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, {[]{return (LogicLensSpiritMQ || CanUse(LENS_OF_TRUTH));}}),
LocationAccess(SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 5);}}),
LocationAccess(SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime);}}),
LocationAccess(SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && (MirrorShield || (SunlightArrows && CanUse(LIGHT_ARROWS)));}}),
LocationAccess(SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 7);}}),
LocationAccess(SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, {[]{return SmallKeys(SPIRIT_TEMPLE, 7);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, {[]{return (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH));}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && (MirrorShield || (SunlightArrows && CanUse(RG_LIGHT_ARROWS)));}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7);}}),
}, {
//Exits
Entrance(SPIRIT_TEMPLE_MQ_LOWER_ADULT, {[]{return MirrorShield && IsAdult && (CanUse(FIRE_ARROWS) || (LogicSpiritMQLowerAdult && CanUse(DINS_FIRE) && Bow));}}),
//Trick: MirrorShield && IsAdult && (CanUse(FIRE_ARROWS) || (LogicSpiritMQLowerAdult && CanUse(DINS_FIRE) && Bow))
Entrance(SPIRIT_TEMPLE_MQ_SHARED, {[]{return true;}}),
Entrance(SPIRIT_TEMPLE_MQ_BOSS_AREA, {[]{return SmallKeys(SPIRIT_TEMPLE, 6) && CanPlay(ZeldasLullaby) && Hammer;}}),
Entrance(SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, {[]{return SmallKeys(SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(LENS_OF_TRUTH));}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT, {[]{return MirrorShield && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQLowerAdult && CanUse(RG_DINS_FIRE) && Bow));}}),
//Trick: MirrorShield && IsAdult && (CanUse(RG_FIRE_ARROWS) || (LogicSpiritMQLowerAdult && CanUse(RG_DINS_FIRE) && Bow))
Entrance(RR_SPIRIT_TEMPLE_MQ_SHARED, {[]{return true;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BOSS_AREA, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 6) && CanPlay(ZeldasLullaby) && Hammer;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 5) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH));}}),
});
areaTable[SPIRIT_TEMPLE_MQ_SHARED] = Area("Spirit Temple MQ Shared", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_SHARED] = Area("Spirit Temple MQ Shared", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 6);}}),
LocationAccess(SPIRIT_TEMPLE_MQ_COMPASS_CHEST, {[]{return (IsChild && CanUse(SLINGSHOT) && SmallKeys(SPIRIT_TEMPLE, 7)) || (IsAdult && CanUse(BOW)) || (Bow && Slingshot);}}),
LocationAccess(SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, {[]{return CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult;}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 6);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, {[]{return (IsChild && CanUse(RG_FAIRY_SLINGSHOT) && SmallKeys(RR_SPIRIT_TEMPLE, 7)) || (IsAdult && CanUse(RG_FAIRY_BOW)) || (Bow && Slingshot);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, {[]{return CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult;}}),
//Trick: CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult
LocationAccess(SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, {[]{return (LogicSpiritMQSunBlockGS && Boomerang && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT)) || IsAdult;}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, {[]{return (LogicSpiritMQSunBlockGS && Boomerang && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT)) || IsAdult;}}),
//Trick: (LogicSpiritMQSunBlockGS && Boomerang && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT)) || IsAdult
}, {
//Exits
Entrance(SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return (SmallKeys(SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(LENS_OF_TRUTH)));}}),
//Trick: (SmallKeys(SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(LENS_OF_TRUTH)))
Entrance(DESERT_COLOSSUS, {[]{return (SmallKeys(SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(LENS_OF_TRUTH)) && IsAdult);}}),
//Trick: (SmallKeys(SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(LENS_OF_TRUTH)) && IsAdult)
Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)));}}),
//Trick: (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)))
Entrance(RR_DESERT_COLOSSUS, {[]{return (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)) && IsAdult);}}),
//Trick: (SmallKeys(RR_SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult)) || (SmallKeys(RR_SPIRIT_TEMPLE, 4) && CanPlay(SongOfTime) && (LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH)) && IsAdult)
});
areaTable[SPIRIT_TEMPLE_MQ_LOWER_ADULT] = Area("Spirit Temple MQ Lower Adult", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_LOWER_ADULT] = Area("Spirit Temple MQ Lower Adult", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, {[]{return true;}}),
LocationAccess(SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, {[]{return SmallKeys(SPIRIT_TEMPLE, 7) && Hammer && Ocarina && SongOfTime && EponasSong && SunsSong && SongOfStorms && ZeldasLullaby;}}),
LocationAccess(SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, {[]{return Hammer;}}),
LocationAccess(SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, {[]{return true;}}),
LocationAccess(SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, {[]{return SmallKeys(SPIRIT_TEMPLE, 7) && Hammer && Ocarina && SongOfTime && EponasSong && SunsSong && SongOfStorms && ZeldasLullaby;}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST, {[]{return true;}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7) && Hammer && Ocarina && SongOfTime && EponasSong && SunsSong && SongOfStorms && ZeldasLullaby;}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, {[]{return Hammer;}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM, {[]{return true;}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, {[]{return SmallKeys(RR_SPIRIT_TEMPLE, 7) && Hammer && Ocarina && SongOfTime && EponasSong && SunsSong && SongOfStorms && ZeldasLullaby;}}),
}, {});
areaTable[SPIRIT_TEMPLE_MQ_BOSS_AREA] = Area("Spirit Temple MQ Boss Area", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_BOSS_AREA] = Area("Spirit Temple MQ Boss Area", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, {[]{return LogicLensSpiritMQ || CanUse(LENS_OF_TRUTH);}}),
LocationAccess(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, {[]{return LogicLensSpiritMQ || CanUse(RG_LENS_OF_TRUTH);}}),
}, {
//Exits
Entrance(SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, {[]{return MirrorShield && Hookshot;}}),
Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, {[]{return MirrorShield && Hookshot;}}),
});
areaTable[SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD] =
Area("Spirit Temple MQ Inside Statue Head", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD] =
Area("Spirit Temple MQ Inside Statue Head", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(SPIRIT_TEMPLE_MQ_SHARED, { [] { return true; } }),
Entrance(SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return BossKeySpiritTemple; } }),
Entrance(RR_SPIRIT_TEMPLE_MQ_SHARED, { [] { return true; } }),
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return BossKeySpiritTemple; } }),
});
areaTable[SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND] = Area("Spirit Temple MQ Mirror Shield Hand", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND] = Area("Spirit Temple MQ Mirror Shield Hand", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, {[]{return true;}}),
LocationAccess(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, {[]{return true;}}),
}, {});
areaTable[SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND] = Area("Spirit Temple MQ Silver Gauntlets Hand", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND] = Area("Spirit Temple MQ Silver Gauntlets Hand", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, {[]{return true;}}),
LocationAccess(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, {[]{return true;}}),
}, {});
}
/*---------------------------
| BOSS ROOM |
---------------------------*/
areaTable[SPIRIT_TEMPLE_BOSS_ENTRYWAY] = Area(
"Spirit Temple Boss Entryway", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY] = Area(
"Spirit Temple Boss Entryway", "Spirit Temple", RHT_SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, { [] { return Dungeon::SpiritTemple.IsVanilla() && false; } }),
Entrance(SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, { [] { return Dungeon::SpiritTemple.IsMQ() && false; } }),
Entrance(SPIRIT_TEMPLE_BOSS_ROOM, { [] { return true; } }),
Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, { [] { return Dungeon::SpiritTemple.IsVanilla() && false; } }),
Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, { [] { return Dungeon::SpiritTemple.IsMQ() && false; } }),
Entrance(RR_SPIRIT_TEMPLE_BOSS_ROOM, { [] { return true; } }),
});
areaTable[SPIRIT_TEMPLE_BOSS_ROOM] = Area(
"Spirit Temple Boss Room", "Spirit Temple", NONE, NO_DAY_NIGHT_CYCLE,
areaTable[RR_SPIRIT_TEMPLE_BOSS_ROOM] = Area(
"Spirit Temple Boss Room", "Spirit Temple", RHT_NONE, NO_DAY_NIGHT_CYCLE,
{
// Events
EventAccess(&SpiritTempleClear, { [] {
return SpiritTempleClear || (HasBossSoul(TWINROVA_BOSS_SOUL) && (CanUse(MIRROR_SHIELD) &&
(CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))));
return SpiritTempleClear || (HasBossSoul(RG_TWINROVA_SOUL) && (CanUse(RG_MIRROR_SHIELD) &&
(CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))));
} }),
},
{
// Locations
LocationAccess(SPIRIT_TEMPLE_TWINROVA_HEART, { [] { return SpiritTempleClear; } }),
LocationAccess(TWINROVA, { [] { return SpiritTempleClear; } }),
LocationAccess(RC_SPIRIT_TEMPLE_TWINROVA_HEART, { [] { return SpiritTempleClear; } }),
LocationAccess(RC_TWINROVA, { [] { return SpiritTempleClear; } }),
},
{
// Exits
Entrance(SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
});
}

View File

@@ -10,11 +10,11 @@ void AreaTable_Init_WaterTemple() {
/*--------------------------
| VANILLA/MQ DECIDER |
---------------------------*/
areaTable[WATER_TEMPLE_ENTRYWAY] = Area("Water Temple Entryway", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_ENTRYWAY] = Area("Water Temple Entryway", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return Dungeon::WaterTemple.IsVanilla();}}),
Entrance(WATER_TEMPLE_MQ_LOBBY, {[]{return Dungeon::WaterTemple.IsMQ();}}),
Entrance(LAKE_HYLIA, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return Dungeon::WaterTemple.IsVanilla();}}),
Entrance(RR_WATER_TEMPLE_MQ_LOBBY, {[]{return Dungeon::WaterTemple.IsMQ();}}),
Entrance(RR_LAKE_HYLIA, {[]{return true;}}),
});
/*--------------------------
@@ -22,230 +22,230 @@ void AreaTable_Init_WaterTemple() {
---------------------------*/
if (Dungeon::WaterTemple.IsVanilla()) {
//Water Temple logic currently assumes that the locked door leading to the upper water raising location is unlocked from the start
areaTable[WATER_TEMPLE_LOBBY] = Area("Water Temple Lobby", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_LOBBY] = Area("Water Temple Lobby", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(WATER_TEMPLE_EAST_LOWER, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(ZORA_TUNIC)) && (CanUse(IRON_BOOTS) || (CanUse(LONGSHOT) && LogicWaterTempleTorchLongshot)));}}),
Entrance(WATER_TEMPLE_NORTH_LOWER, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(ZORA_TUNIC)) && CanUse(IRON_BOOTS));}}),
Entrance(WATER_TEMPLE_SOUTH_LOWER, {[]{return WaterTempleLow && HasExplosives && (CanDive || CanUse(IRON_BOOTS)) && (LogicFewerTunicRequirements || CanUse(ZORA_TUNIC));}}),
Entrance(WATER_TEMPLE_WEST_LOWER, {[]{return WaterTempleLow && GoronBracelet && (IsChild || CanDive || CanUse(IRON_BOOTS)) && (LogicFewerTunicRequirements || CanUse(ZORA_TUNIC));}}),
Entrance(WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return WaterTempleLow && SmallKeys(WATER_TEMPLE, 5);}}),
Entrance(WATER_TEMPLE_CENTRAL_PILLAR_UPPER, {[]{return (WaterTempleLow || WaterTempleMiddle) && (HasFireSourceWithTorch || CanUse(BOW));}}),
Entrance(WATER_TEMPLE_EAST_MIDDLE, {[]{return (WaterTempleLow || WaterTempleMiddle || (CanUse(IRON_BOOTS) && WaterTimer >= 16)) && CanUse(HOOKSHOT);}}),
Entrance(WATER_TEMPLE_WEST_MIDDLE, {[]{return WaterTempleMiddle;}}),
Entrance(WATER_TEMPLE_HIGH_WATER, {[]{return IsAdult && (CanUse(HOVER_BOOTS) || (LogicDamageBoost && Bombs && CanTakeDamage));}}),
Entrance(WATER_TEMPLE_BLOCK_CORRIDOR, {[]{return (WaterTempleLow || WaterTempleMiddle) && (CanUse(SLINGSHOT) || CanUse(BOW)) && (CanUse(LONGSHOT) || CanUse(HOVER_BOOTS) || (LogicWaterCentralBow && (IsAdult || WaterTempleMiddle)));}}),
Entrance(WATER_TEMPLE_FALLING_PLATFORM_ROOM, {[]{return WaterTempleHigh && SmallKeys(WATER_TEMPLE, 4);}}),
Entrance(WATER_TEMPLE_PRE_BOSS_ROOM, {[]{return WaterTempleHigh && CanUse(LONGSHOT);}}),
Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC)) && (CanUse(RG_IRON_BOOTS) || (CanUse(RG_LONGSHOT) && LogicWaterTempleTorchLongshot)));}}),
Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}),
Entrance(RR_WATER_TEMPLE_SOUTH_LOWER, {[]{return WaterTempleLow && HasExplosives && (CanDive || CanUse(RG_IRON_BOOTS)) && (LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC));}}),
Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return WaterTempleLow && GoronBracelet && (IsChild || CanDive || CanUse(RG_IRON_BOOTS)) && (LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC));}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return WaterTempleLow && SmallKeys(RR_WATER_TEMPLE, 5);}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER, {[]{return (WaterTempleLow || WaterTempleMiddle) && (HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW));}}),
Entrance(RR_WATER_TEMPLE_EAST_MIDDLE, {[]{return (WaterTempleLow || WaterTempleMiddle || (CanUse(RG_IRON_BOOTS) && WaterTimer >= 16)) && CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_WEST_MIDDLE, {[]{return WaterTempleMiddle;}}),
Entrance(RR_WATER_TEMPLE_HIGH_WATER, {[]{return IsAdult && (CanUse(RG_HOVER_BOOTS) || (LogicDamageBoost && Bombs && CanTakeDamage));}}),
Entrance(RR_WATER_TEMPLE_BLOCK_CORRIDOR, {[]{return (WaterTempleLow || WaterTempleMiddle) && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (CanUse(RG_LONGSHOT) || CanUse(RG_HOVER_BOOTS) || (LogicWaterCentralBow && (IsAdult || WaterTempleMiddle)));}}),
Entrance(RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM, {[]{return WaterTempleHigh && SmallKeys(RR_WATER_TEMPLE, 4);}}),
Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, {[]{return WaterTempleHigh && CanUse(RG_LONGSHOT);}}),
});
areaTable[WATER_TEMPLE_EAST_LOWER] = Area("Water Temple East Lower", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_WATER_TEMPLE_EAST_LOWER] = Area("Water Temple East Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&WaterTempleLow, {[]{return WaterTempleLow || CanPlay(ZeldasLullaby);}}),
}, {}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(ZORA_TUNIC)) && CanUse(IRON_BOOTS));}}),
Entrance(WATER_TEMPLE_MAP_ROOM, {[]{return WaterTempleHigh;}}),
Entrance(WATER_TEMPLE_CRACKED_WALL, {[]{return WaterTempleMiddle || (WaterTempleHigh && WaterTempleLow && ((CanUse(HOVER_BOOTS) && LogicWaterCrackedWallHovers) || LogicWaterCrackedWallNothing));}}),
Entrance(WATER_TEMPLE_TORCH_ROOM, {[]{return WaterTempleLow && (HasFireSourceWithTorch || CanUse(BOW));}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(RG_ZORA_TUNIC)) && CanUse(RG_IRON_BOOTS));}}),
Entrance(RR_WATER_TEMPLE_MAP_ROOM, {[]{return WaterTempleHigh;}}),
Entrance(RR_WATER_TEMPLE_CRACKED_WALL, {[]{return WaterTempleMiddle || (WaterTempleHigh && WaterTempleLow && ((CanUse(RG_HOVER_BOOTS) && LogicWaterCrackedWallHovers) || LogicWaterCrackedWallNothing));}}),
Entrance(RR_WATER_TEMPLE_TORCH_ROOM, {[]{return WaterTempleLow && (HasFireSourceWithTorch || CanUse(RG_FAIRY_BOW));}}),
});
areaTable[WATER_TEMPLE_MAP_ROOM] = Area("Water Temple Map Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_MAP_ROOM] = Area("Water Temple Map Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_MAP_CHEST, {[]{return (MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT);}}),
LocationAccess(RC_WATER_TEMPLE_MAP_CHEST, {[]{return (MagicMeter && CanUse(RG_KOKIRI_SWORD)) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_HOOKSHOT);}}),
}, {
//Exits
Entrance(WATER_TEMPLE_EAST_LOWER, {[]{return (MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return (MagicMeter && CanUse(RG_KOKIRI_SWORD)) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_HOOKSHOT);}}),
});
areaTable[WATER_TEMPLE_CRACKED_WALL] = Area("Water Temple Cracked Wall", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_CRACKED_WALL] = Area("Water Temple Cracked Wall", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_CRACKED_WALL_CHEST, {[]{return HasExplosives;}}),
LocationAccess(RC_WATER_TEMPLE_CRACKED_WALL_CHEST, {[]{return HasExplosives;}}),
}, {
//Exits
Entrance(WATER_TEMPLE_EAST_LOWER, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return true;}}),
});
areaTable[WATER_TEMPLE_TORCH_ROOM] = Area("Water Temple Torch Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_TORCH_ROOM] = Area("Water Temple Torch Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_TORCHES_CHEST, {[]{return (MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT);}}),
LocationAccess(RC_WATER_TEMPLE_TORCHES_CHEST, {[]{return (MagicMeter && CanUse(RG_KOKIRI_SWORD)) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_HOOKSHOT);}}),
}, {
//Exits
Entrance(WATER_TEMPLE_EAST_LOWER, {[]{return (MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_EAST_LOWER, {[]{return (MagicMeter && CanUse(RG_KOKIRI_SWORD)) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_HOOKSHOT);}}),
});
areaTable[WATER_TEMPLE_NORTH_LOWER] = Area("Water Temple North Lower", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_NORTH_LOWER] = Area("Water Temple North Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(WATER_TEMPLE_BOULDERS_LOWER, {[]{return (CanUse(LONGSHOT) || (LogicWaterBossKeyRegion && CanUse(HOVER_BOOTS))) && SmallKeys(WATER_TEMPLE, 4);}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, {[]{return (CanUse(RG_LONGSHOT) || (LogicWaterBossKeyRegion && CanUse(RG_HOVER_BOOTS))) && SmallKeys(RR_WATER_TEMPLE, 4);}}),
});
areaTable[WATER_TEMPLE_BOULDERS_LOWER] = Area("Water Temple Boulders Lower", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_BOULDERS_LOWER] = Area("Water Temple Boulders Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, {[]{return CanUse(LONGSHOT) || Here(WATER_TEMPLE_BOULDERS_UPPER, []{return (IsAdult && HookshotOrBoomerang) || (CanUse(IRON_BOOTS) && CanUse(HOOKSHOT));});}}),
LocationAccess(RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST, {[]{return CanUse(RG_LONGSHOT) || Here(RR_WATER_TEMPLE_BOULDERS_UPPER, []{return (IsAdult && HookshotOrBoomerang) || (CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT));});}}),
}, {
//Exits
Entrance(WATER_TEMPLE_NORTH_LOWER, {[]{return SmallKeys(WATER_TEMPLE, 4);}}),
Entrance(WATER_TEMPLE_BLOCK_ROOM, {[]{return true;}}),
Entrance(WATER_TEMPLE_BOULDERS_UPPER, {[]{return (IsAdult && (CanUse(HOVER_BOOTS) || LogicWaterNorthBasementLedgeJump)) || (CanUse(HOVER_BOOTS) && CanUse(IRON_BOOTS));}}),
Entrance(RR_WATER_TEMPLE_NORTH_LOWER, {[]{return SmallKeys(RR_WATER_TEMPLE, 4);}}),
Entrance(RR_WATER_TEMPLE_BLOCK_ROOM, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (IsAdult && (CanUse(RG_HOVER_BOOTS) || LogicWaterNorthBasementLedgeJump)) || (CanUse(RG_HOVER_BOOTS) && CanUse(RG_IRON_BOOTS));}}),
});
areaTable[WATER_TEMPLE_BLOCK_ROOM] = Area("Water Temple Block Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_BLOCK_ROOM] = Area("Water Temple Block Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_BOULDERS_LOWER, {[]{return (GoronBracelet && HasExplosives) || CanUse(HOOKSHOT);}}),
Entrance(WATER_TEMPLE_JETS_ROOM, {[]{return (GoronBracelet && HasExplosives) || (CanUse(HOOKSHOT) && CanUse(HOVER_BOOTS));}}),
Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, {[]{return (GoronBracelet && HasExplosives) || CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_JETS_ROOM, {[]{return (GoronBracelet && HasExplosives) || (CanUse(RG_HOOKSHOT) && CanUse(RG_HOVER_BOOTS));}}),
});
areaTable[WATER_TEMPLE_JETS_ROOM] = Area("Water Temple Jets Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_JETS_ROOM] = Area("Water Temple Jets Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_BLOCK_ROOM, {[]{return CanUse(HOOKSHOT);}}),
Entrance(WATER_TEMPLE_BOULDERS_UPPER, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_BLOCK_ROOM, {[]{return CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return true;}}),
});
areaTable[WATER_TEMPLE_BOULDERS_UPPER] = Area("Water Temple Boulders Upper", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_BOULDERS_UPPER] = Area("Water Temple Boulders Upper", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_BOULDERS_LOWER, {[]{return true;}}),
Entrance(WATER_TEMPLE_JETS_ROOM, {[]{return IsAdult;}}),
Entrance(WATER_TEMPLE_BOSS_KEY_ROOM, {[]{return (CanUse(IRON_BOOTS) || (IsAdult && LogicWaterBKJumpDive)) && SmallKeys(WATER_TEMPLE, 5);}}),
Entrance(RR_WATER_TEMPLE_BOULDERS_LOWER, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_JETS_ROOM, {[]{return IsAdult;}}),
Entrance(RR_WATER_TEMPLE_BOSS_KEY_ROOM, {[]{return (CanUse(RG_IRON_BOOTS) || (IsAdult && LogicWaterBKJumpDive)) && SmallKeys(RR_WATER_TEMPLE, 5);}}),
});
areaTable[WATER_TEMPLE_BOSS_KEY_ROOM] = Area("Water Temple Boss Key Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_WATER_TEMPLE_BOSS_KEY_ROOM] = Area("Water Temple Boss Key Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(WATER_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}),
LocationAccess(RC_WATER_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(WATER_TEMPLE_BOULDERS_UPPER, {[]{return (CanUse(IRON_BOOTS) || (IsAdult && LogicWaterBKJumpDive) || IsChild || CanDive) && SmallKeys(WATER_TEMPLE, 5);}}),
Entrance(RR_WATER_TEMPLE_BOULDERS_UPPER, {[]{return (CanUse(RG_IRON_BOOTS) || (IsAdult && LogicWaterBKJumpDive) || IsChild || CanDive) && SmallKeys(RR_WATER_TEMPLE, 5);}}),
});
areaTable[WATER_TEMPLE_SOUTH_LOWER] = Area("Water Temple South Lower", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_SOUTH_LOWER] = Area("Water Temple South Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_GS_BEHIND_GATE, {[]{return CanUse(HOOKSHOT) || (IsAdult && CanUse(HOVER_BOOTS));}}),
LocationAccess(RC_WATER_TEMPLE_GS_BEHIND_GATE, {[]{return CanUse(RG_HOOKSHOT) || (IsAdult && CanUse(RG_HOVER_BOOTS));}}),
}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return CanUse(IRON_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return CanUse(RG_IRON_BOOTS);}}),
});
areaTable[WATER_TEMPLE_WEST_LOWER] = Area("Water Temple West Lower", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_WEST_LOWER] = Area("Water Temple West Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return CanUse(HOOKSHOT) && CanUse(IRON_BOOTS) && GoronBracelet;}}),
Entrance(WATER_TEMPLE_DRAGON_ROOM, {[]{return IsAdult || CanChildAttack;}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return CanUse(RG_HOOKSHOT) && CanUse(RG_IRON_BOOTS) && GoronBracelet;}}),
Entrance(RR_WATER_TEMPLE_DRAGON_ROOM, {[]{return IsAdult || CanChildAttack;}}),
});
areaTable[WATER_TEMPLE_DRAGON_ROOM] = Area("Water Temple Dragon Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_DRAGON_ROOM] = Area("Water Temple Dragon Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_DRAGON_CHEST, {[]{return (CanUse(HOOKSHOT) && CanUse(IRON_BOOTS)) || (((IsAdult && LogicWaterDragonAdult && (CanUse(HOOKSHOT) || CanUse(BOW) || HasBombchus)) || (IsChild && LogicWaterDragonChild && (CanUse(SLINGSHOT) || CanUse(BOOMERANG) || HasBombchus))) && (CanDive || CanUse(IRON_BOOTS))) ||
Here(WATER_TEMPLE_RIVER, []{return IsAdult && CanUse(BOW) && ((LogicWaterDragonAdult && (CanDive || CanUse(IRON_BOOTS))) || LogicWaterDragonJumpDive);});}}),
LocationAccess(RC_WATER_TEMPLE_DRAGON_CHEST, {[]{return (CanUse(RG_HOOKSHOT) && CanUse(RG_IRON_BOOTS)) || (((IsAdult && LogicWaterDragonAdult && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || HasBombchus)) || (IsChild && LogicWaterDragonChild && (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG) || HasBombchus))) && (CanDive || CanUse(RG_IRON_BOOTS))) ||
Here(RR_WATER_TEMPLE_RIVER, []{return IsAdult && CanUse(RG_FAIRY_BOW) && ((LogicWaterDragonAdult && (CanDive || CanUse(RG_IRON_BOOTS))) || LogicWaterDragonJumpDive);});}}),
}, {
//Exits
Entrance(WATER_TEMPLE_WEST_LOWER, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_WEST_LOWER, {[]{return true;}}),
});
areaTable[WATER_TEMPLE_CENTRAL_PILLAR_LOWER] = Area("Water Temple Central Pillar Lower", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER] = Area("Water Temple Central Pillar Lower", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return SmallKeys(WATER_TEMPLE, 5);}}),
Entrance(WATER_TEMPLE_CENTRAL_PILLAR_UPPER, {[]{return CanUse(HOOKSHOT);}}),
Entrance(WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT, {[]{return WaterTempleMiddle && CanUse(IRON_BOOTS) && WaterTimer >= 40;}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return SmallKeys(RR_WATER_TEMPLE, 5);}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER, {[]{return CanUse(RG_HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT, {[]{return WaterTempleMiddle && CanUse(RG_IRON_BOOTS) && WaterTimer >= 40;}}),
});
areaTable[WATER_TEMPLE_CENTRAL_PILLAR_UPPER] = Area("Water Temple Central Pillar Upper", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_UPPER] = Area("Water Temple Central Pillar Upper", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&WaterTempleMiddle, {[]{return WaterTempleMiddle || CanPlay(ZeldasLullaby);}}),
}, {
//Locations
LocationAccess(WATER_TEMPLE_GS_CENTRAL_PILLAR, {[]{return CanUse(LONGSHOT) || (((LogicWaterCentralGSFW && CanUse(FARORES_WIND) && (CanUse(BOW) || CanUse(DINS_FIRE) || SmallKeys(WATER_TEMPLE, 5))) || (LogicWaterCentralGSIrons && CanUse(IRON_BOOTS) && ((CanUse(HOOKSHOT) && CanUse(BOW)) || (CanUse(DINS_FIRE))))) && WaterTempleHigh && HookshotOrBoomerang);}}),
LocationAccess(RC_WATER_TEMPLE_GS_CENTRAL_PILLAR, {[]{return CanUse(RG_LONGSHOT) || (((LogicWaterCentralGSFW && CanUse(RG_FARORES_WIND) && (CanUse(RG_FAIRY_BOW) || CanUse(RG_DINS_FIRE) || SmallKeys(RR_WATER_TEMPLE, 5))) || (LogicWaterCentralGSIrons && CanUse(RG_IRON_BOOTS) && ((CanUse(RG_HOOKSHOT) && CanUse(RG_FAIRY_BOW)) || (CanUse(RG_DINS_FIRE))))) && WaterTempleHigh && HookshotOrBoomerang);}}),
}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return true;}}),
});
areaTable[WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT] = Area("Water Temple Central Pillar Basement", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT] = Area("Water Temple Central Pillar Basement", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_CENTRAL_PILLAR_CHEST, {[]{return CanUse(HOOKSHOT) && CanUse(IRON_BOOTS) && WaterTimer >= 40;}}),
LocationAccess(RC_WATER_TEMPLE_CENTRAL_PILLAR_CHEST, {[]{return CanUse(RG_HOOKSHOT) && CanUse(RG_IRON_BOOTS) && WaterTimer >= 40;}}),
}, {
//Exits
Entrance(WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return CanUse(IRON_BOOTS) && WaterTimer >= 16;}}),
Entrance(RR_WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return CanUse(RG_IRON_BOOTS) && WaterTimer >= 16;}}),
});
areaTable[WATER_TEMPLE_EAST_MIDDLE] = Area("Water Temple East Middle", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_EAST_MIDDLE] = Area("Water Temple East Middle", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_COMPASS_CHEST, {[]{return CanUseProjectile;}}),
LocationAccess(RC_WATER_TEMPLE_COMPASS_CHEST, {[]{return CanUseProjectile;}}),
}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return CanUse(IRON_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return CanUse(RG_IRON_BOOTS);}}),
});
areaTable[WATER_TEMPLE_WEST_MIDDLE] = Area("Water Temple West Middle", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_WEST_MIDDLE] = Area("Water Temple West Middle", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(WATER_TEMPLE_HIGH_WATER, {[]{return CanUseProjectile;}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_HIGH_WATER, {[]{return CanUseProjectile;}}),
});
areaTable[WATER_TEMPLE_HIGH_WATER] = Area("Water Temple High Water", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_WATER_TEMPLE_HIGH_WATER] = Area("Water Temple High Water", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&WaterTempleHigh, {[]{return WaterTempleHigh || CanPlay(ZeldasLullaby);}}),
}, {}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}),
});
areaTable[WATER_TEMPLE_BLOCK_CORRIDOR] = Area("Water Temple Block Corridor", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_BLOCK_CORRIDOR] = Area("Water Temple Block Corridor", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, {[]{return GoronBracelet && (WaterTempleLow || WaterTempleMiddle);}}),
LocationAccess(RC_WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, {[]{return GoronBracelet && (WaterTempleLow || WaterTempleMiddle);}}),
}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return CanUse(HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return CanUse(RG_HOOKSHOT);}}),
});
areaTable[WATER_TEMPLE_FALLING_PLATFORM_ROOM] = Area("Water Temple Falling Platform Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM] = Area("Water Temple Falling Platform Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, {[]{return CanUse(LONGSHOT) || (LogicWaterFallingPlatformGSBoomerang && IsChild && CanUse(BOOMERANG)) || (LogicWaterFallingPlatformGSHookshot && IsAdult && CanUse(HOOKSHOT));}}),
LocationAccess(RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, {[]{return CanUse(RG_LONGSHOT) || (LogicWaterFallingPlatformGSBoomerang && IsChild && CanUse(RG_BOOMERANG)) || (LogicWaterFallingPlatformGSHookshot && IsAdult && CanUse(RG_HOOKSHOT));}}),
}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return CanUse(HOOKSHOT) && SmallKeys(WATER_TEMPLE, 4);}}),
Entrance(WATER_TEMPLE_DRAGON_PILLARS_ROOM, {[]{return CanUse(HOOKSHOT) && SmallKeys(WATER_TEMPLE, 5);}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return CanUse(RG_HOOKSHOT) && SmallKeys(RR_WATER_TEMPLE, 4);}}),
Entrance(RR_WATER_TEMPLE_DRAGON_PILLARS_ROOM, {[]{return CanUse(RG_HOOKSHOT) && SmallKeys(RR_WATER_TEMPLE, 5);}}),
});
areaTable[WATER_TEMPLE_DRAGON_PILLARS_ROOM] = Area("Water Temple Dragon Pillars Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_DRAGON_PILLARS_ROOM] = Area("Water Temple Dragon Pillars Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_FALLING_PLATFORM_ROOM, {[]{return CanUseProjectile;}}),
Entrance(WATER_TEMPLE_DARK_LINK_ROOM, {[]{return CanUse(HOOKSHOT);}}),
Entrance(RR_WATER_TEMPLE_FALLING_PLATFORM_ROOM, {[]{return CanUseProjectile;}}),
Entrance(RR_WATER_TEMPLE_DARK_LINK_ROOM, {[]{return CanUse(RG_HOOKSHOT);}}),
});
areaTable[WATER_TEMPLE_DARK_LINK_ROOM] = Area("Water Temple Dark Link Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_DARK_LINK_ROOM] = Area("Water Temple Dark Link Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_DRAGON_PILLARS_ROOM, {[]{return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);}}),
Entrance(WATER_TEMPLE_LONGSHOT_ROOM, {[]{return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);}}),
Entrance(RR_WATER_TEMPLE_DRAGON_PILLARS_ROOM, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
Entrance(RR_WATER_TEMPLE_LONGSHOT_ROOM, {[]{return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);}}),
});
areaTable[WATER_TEMPLE_LONGSHOT_ROOM] = Area("Water Temple Longshot Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_LONGSHOT_ROOM] = Area("Water Temple Longshot Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_LONGSHOT_CHEST, {[]{return true;}}),
LocationAccess(RC_WATER_TEMPLE_LONGSHOT_CHEST, {[]{return true;}}),
}, {
//Exits
Entrance(WATER_TEMPLE_DARK_LINK_ROOM, {[]{return true;}}),
Entrance(WATER_TEMPLE_RIVER, {[]{return IsChild || CanPlay(SongOfTime);}}),
Entrance(RR_WATER_TEMPLE_DARK_LINK_ROOM, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_RIVER, {[]{return IsChild || CanPlay(SongOfTime);}}),
});
areaTable[WATER_TEMPLE_RIVER] = Area("Water Temple River", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_RIVER] = Area("Water Temple River", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_RIVER_CHEST, {[]{return (CanUse(SLINGSHOT) || CanUse(BOW)) && (IsAdult || CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT));}}),
LocationAccess(WATER_TEMPLE_GS_RIVER, {[]{return (CanUse(IRON_BOOTS) && CanUse(HOOKSHOT)) || (LogicWaterRiverGS && CanUse(LONGSHOT));}}),
LocationAccess(RC_WATER_TEMPLE_RIVER_CHEST, {[]{return (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (IsAdult || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
LocationAccess(RC_WATER_TEMPLE_GS_RIVER, {[]{return (CanUse(RG_IRON_BOOTS) && CanUse(RG_HOOKSHOT)) || (LogicWaterRiverGS && CanUse(RG_LONGSHOT));}}),
}, {
//Exits
Entrance(WATER_TEMPLE_DRAGON_ROOM, {[]{return (CanUse(SLINGSHOT) || CanUse(BOW)) && (IsAdult || CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT));}}),
Entrance(RR_WATER_TEMPLE_DRAGON_ROOM, {[]{return (CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW)) && (IsAdult || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT));}}),
});
areaTable[WATER_TEMPLE_PRE_BOSS_ROOM] = Area("Water Temple Pre Boss Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_WATER_TEMPLE_PRE_BOSS_ROOM] = Area("Water Temple Pre Boss Room", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
}, {}, {
//Exits
Entrance(WATER_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(WATER_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyWaterTemple;}}),
Entrance(RR_WATER_TEMPLE_LOBBY, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyWaterTemple;}}),
});
}
@@ -253,82 +253,82 @@ void AreaTable_Init_WaterTemple() {
| MASTER QUEST DUNGEON |
---------------------------*/
if (Dungeon::WaterTemple.IsMQ()) {
areaTable[WATER_TEMPLE_MQ_LOBBY] = Area("Water Temple MQ Lobby", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_WATER_TEMPLE_MQ_LOBBY] = Area("Water Temple MQ Lobby", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(WATER_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(WATER_TEMPLE_MQ_DIVE, {[]{return IsAdult && WaterTimer >= 24 && CanUse(IRON_BOOTS);}}),
Entrance(WATER_TEMPLE_MQ_DARK_LINK_REGION, {[]{return SmallKeys(WATER_TEMPLE, 1) && IsAdult && CanUse(LONGSHOT);}}),
Entrance(WATER_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyWaterTemple && IsAdult && CanUse(LONGSHOT);}}),
Entrance(RR_WATER_TEMPLE_ENTRYWAY, {[]{return true;}}),
Entrance(RR_WATER_TEMPLE_MQ_DIVE, {[]{return IsAdult && WaterTimer >= 24 && CanUse(RG_IRON_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_MQ_DARK_LINK_REGION, {[]{return SmallKeys(RR_WATER_TEMPLE, 1) && IsAdult && CanUse(RG_LONGSHOT);}}),
Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, {[]{return BossKeyWaterTemple && IsAdult && CanUse(RG_LONGSHOT);}}),
});
areaTable[WATER_TEMPLE_MQ_DIVE] = Area("Water Temple MQ Dive", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_MQ_DIVE] = Area("Water Temple MQ Dive", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_MQ_MAP_CHEST, {[]{return HasFireSource && IsAdult && CanUse(HOOKSHOT);}}),
LocationAccess(WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, {[]{return IsAdult && CanUse(ZORA_TUNIC) && CanUse(HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(FIRE_ARROWS)) || (CanUse(DINS_FIRE) && CanPlay(SongOfTime)));}}),
//Trick: IsAdult && CanUse(ZORA_TUNIC) && CanUse(HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(FIRE_ARROWS)) || (CanUse(DINS_FIRE) && CanPlay(SongOfTime)))
LocationAccess(RC_WATER_TEMPLE_MQ_MAP_CHEST, {[]{return HasFireSource && IsAdult && CanUse(RG_HOOKSHOT);}}),
LocationAccess(RC_WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST, {[]{return IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanPlay(SongOfTime)));}}),
//Trick: IsAdult && CanUse(RG_ZORA_TUNIC) && CanUse(RG_HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(RG_FIRE_ARROWS)) || (CanUse(RG_DINS_FIRE) && CanPlay(SongOfTime)))
}, {
//Exits
Entrance(WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS, {[]{return CanPlay(ZeldasLullaby);}}),
Entrance(RR_WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS, {[]{return CanPlay(ZeldasLullaby);}}),
});
areaTable[WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS] = Area("Water Temple MQ Lowered Water Levels", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS] = Area("Water Temple MQ Lowered Water Levels", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_MQ_COMPASS_CHEST, {[]{return (IsAdult && CanUse(BOW)) || CanUse(DINS_FIRE) || Here(WATER_TEMPLE_MQ_LOBBY, []{return IsChild && CanUse(STICKS) && HasExplosives;});}}),
LocationAccess(WATER_TEMPLE_MQ_LONGSHOT_CHEST, {[]{return IsAdult && CanUse(HOOKSHOT);}}),
LocationAccess(WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, {[]{return CanUse(DINS_FIRE);}}),
LocationAccess(WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, {[]{return IsAdult && CanUse(LONGSHOT);}}),
LocationAccess(RC_WATER_TEMPLE_MQ_COMPASS_CHEST, {[]{return (IsAdult && CanUse(RG_FAIRY_BOW)) || CanUse(RG_DINS_FIRE) || Here(RR_WATER_TEMPLE_MQ_LOBBY, []{return IsChild && CanUse(RG_STICKS) && HasExplosives;});}}),
LocationAccess(RC_WATER_TEMPLE_MQ_LONGSHOT_CHEST, {[]{return IsAdult && CanUse(RG_HOOKSHOT);}}),
LocationAccess(RC_WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY, {[]{return CanUse(RG_DINS_FIRE);}}),
LocationAccess(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, {[]{return IsAdult && CanUse(RG_LONGSHOT);}}),
}, {});
areaTable[WATER_TEMPLE_MQ_DARK_LINK_REGION] = Area("Water Temple MQ Dark Link Region", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_WATER_TEMPLE_MQ_DARK_LINK_REGION] = Area("Water Temple MQ Dark Link Region", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FairyPot, {[]{return true;}}),
EventAccess(&NutPot, {[]{return true;}}),
}, {
//Locations
LocationAccess(WATER_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return IsAdult && WaterTimer >= 24 && CanUse(DINS_FIRE) && (LogicWaterDragonJumpDive || CanDive || CanUse(IRON_BOOTS));}}),
LocationAccess(WATER_TEMPLE_MQ_GS_RIVER, {[]{return true;}}),
LocationAccess(RC_WATER_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return IsAdult && WaterTimer >= 24 && CanUse(RG_DINS_FIRE) && (LogicWaterDragonJumpDive || CanDive || CanUse(RG_IRON_BOOTS));}}),
LocationAccess(RC_WATER_TEMPLE_MQ_GS_RIVER, {[]{return true;}}),
}, {
//Exits
Entrance(WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS, {[]{return IsAdult && WaterTimer >= 24 && CanUse(DINS_FIRE) && CanUse(IRON_BOOTS);}}),
Entrance(RR_WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS, {[]{return IsAdult && WaterTimer >= 24 && CanUse(RG_DINS_FIRE) && CanUse(RG_IRON_BOOTS);}}),
});
areaTable[WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS] = Area("Water Temple MQ Basement Gated Areas", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS] = Area("Water Temple MQ Basement Gated Areas", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(WATER_TEMPLE_MQ_FREESTANDING_KEY, {[]{return HoverBoots || CanUse(SCARECROW) || LogicWaterNorthBasementLedgeJump;}}),
LocationAccess(WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, {[]{return CanUse(FIRE_ARROWS) && (HoverBoots || CanUse(SCARECROW));}}),
LocationAccess(WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, {[]{return LogicWaterMQLockedGS || (SmallKeys(WATER_TEMPLE, 2) && (HoverBoots || CanUse(SCARECROW) || LogicWaterNorthBasementLedgeJump));}}),
//Trick: LogicWaterMQLockedGS || (SmallKeys(WATER_TEMPLE, 2) && (HoverBoots || CanUse(SCARECROW) || LogicWaterNorthBasementLedgeJump))
LocationAccess(RC_WATER_TEMPLE_MQ_FREESTANDING_KEY, {[]{return HoverBoots || CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump;}}),
LocationAccess(RC_WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH, {[]{return CanUse(RG_FIRE_ARROWS) && (HoverBoots || CanUse(RG_SCARECROW));}}),
LocationAccess(RC_WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA, {[]{return LogicWaterMQLockedGS || (SmallKeys(RR_WATER_TEMPLE, 2) && (HoverBoots || CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump));}}),
//Trick: LogicWaterMQLockedGS || (SmallKeys(RR_WATER_TEMPLE, 2) && (HoverBoots || CanUse(RG_SCARECROW) || LogicWaterNorthBasementLedgeJump))
}, {});
}
/*---------------------------
| BOSS ROOM |
---------------------------*/
areaTable[WATER_TEMPLE_BOSS_ENTRYWAY] =
Area("Water Temple Boss Entryway", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
areaTable[RR_WATER_TEMPLE_BOSS_ENTRYWAY] =
Area("Water Temple Boss Entryway", "Water Temple", RHT_WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {},
{
// Exits
Entrance(WATER_TEMPLE_PRE_BOSS_ROOM, { [] { return Dungeon::WaterTemple.IsVanilla() && false; } }),
Entrance(WATER_TEMPLE_MQ_LOBBY, { [] { return Dungeon::WaterTemple.IsMQ() && false; } }),
Entrance(WATER_TEMPLE_BOSS_ROOM, { [] { return true; } }),
Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, { [] { return Dungeon::WaterTemple.IsVanilla() && false; } }),
Entrance(RR_WATER_TEMPLE_MQ_LOBBY, { [] { return Dungeon::WaterTemple.IsMQ() && false; } }),
Entrance(RR_WATER_TEMPLE_BOSS_ROOM, { [] { return true; } }),
});
areaTable[WATER_TEMPLE_BOSS_ROOM] = Area(
"Water Temple Boss Room", "Water Temple", NONE, NO_DAY_NIGHT_CYCLE,
areaTable[RR_WATER_TEMPLE_BOSS_ROOM] = Area(
"Water Temple Boss Room", "Water Temple", RHT_NONE, NO_DAY_NIGHT_CYCLE,
{
// Events
EventAccess(&WaterTempleClear, { [] {
return WaterTempleClear || (HasBossSoul(MORPHA_BOSS_SOUL) &&
(CanUse(HOOKSHOT) && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))));
return WaterTempleClear || (HasBossSoul(RG_MORPHA_SOUL) &&
(CanUse(RG_HOOKSHOT) && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))));
} }),
},
{
// Locations
LocationAccess(WATER_TEMPLE_MORPHA_HEART, { [] { return WaterTempleClear; } }),
LocationAccess(MORPHA, { [] { return WaterTempleClear; } }),
LocationAccess(RC_WATER_TEMPLE_MORPHA_HEART, { [] { return WaterTempleClear; } }),
LocationAccess(RC_MORPHA, { [] { return WaterTempleClear; } }),
},
{
// Exits
Entrance(WATER_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
});
}

View File

@@ -6,81 +6,81 @@ using namespace Logic;
using namespace Settings;
void AreaTable_Init_ZorasDomain() {
areaTable[ZR_FRONT] = Area("ZR Front", "Zora River", ZORAS_RIVER, DAY_NIGHT_CYCLE, {}, {
areaTable[RR_ZR_FRONT] = Area("ZR Front", "Zora River", RHT_ZORAS_RIVER, DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(ZR_GS_TREE, {[]{return IsChild && CanChildAttack;}}),
LocationAccess(RC_ZR_GS_TREE, {[]{return IsChild && CanChildAttack;}}),
}, {
//Exits
Entrance(ZORAS_RIVER, {[]{return IsAdult || CanBlastOrSmash;}}),
Entrance(HYRULE_FIELD, {[]{return true;}}),
Entrance(RR_ZORAS_RIVER, {[]{return IsAdult || CanBlastOrSmash;}}),
Entrance(RR_HYRULE_FIELD, {[]{return true;}}),
});
areaTable[ZORAS_RIVER] = Area("Zora River", "Zora River", ZORAS_RIVER, DAY_NIGHT_CYCLE, {
areaTable[RR_ZORAS_RIVER] = Area("Zora River", "Zora River", RHT_ZORAS_RIVER, DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(ZORAS_RIVER) && CanPlay(SongOfStorms));}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(STICKS);}}),
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(RR_ZORAS_RIVER) && CanPlay(SongOfStorms));}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(RG_STICKS);}}),
EventAccess(&BugShrub, {[]{return BugShrub || CanCutShrubs;}}),
}, {
//Locations
LocationAccess(ZR_MAGIC_BEAN_SALESMAN, {[]{return IsChild;}}),
LocationAccess(ZR_FROGS_OCARINA_GAME, {[]{return IsChild && CanPlay(ZeldasLullaby) && CanPlay(SariasSong) && CanPlay(SunsSong) && CanPlay(EponasSong) && CanPlay(SongOfTime) && CanPlay(SongOfStorms);}}),
LocationAccess(ZR_FROGS_IN_THE_RAIN, {[]{return IsChild && CanPlay(SongOfStorms);}}),
LocationAccess(ZR_FROGS_ZELDAS_LULLABY, {[]{return IsChild && CanPlay(ZeldasLullaby);}}),
LocationAccess(ZR_FROGS_EPONAS_SONG, {[]{return IsChild && CanPlay(EponasSong);}}),
LocationAccess(ZR_FROGS_SARIAS_SONG, {[]{return IsChild && CanPlay(SariasSong);}}),
LocationAccess(ZR_FROGS_SUNS_SONG, {[]{return IsChild && CanPlay(SunsSong);}}),
LocationAccess(ZR_FROGS_SONG_OF_TIME, {[]{return IsChild && CanPlay(SongOfTime);}}),
LocationAccess(ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, {[]{return IsChild || CanUse(HOVER_BOOTS) || (IsAdult && LogicZoraRiverLower);}}),
LocationAccess(ZR_NEAR_DOMAIN_FREESTANDING_POH, {[]{return IsChild || CanUse(HOVER_BOOTS) || (IsAdult && LogicZoraRiverUpper);}}),
LocationAccess(ZR_GS_LADDER, {[]{return IsChild && AtNight && CanChildAttack && CanGetNightTimeGS;}}),
LocationAccess(ZR_GS_NEAR_RAISED_GROTTOS, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(ZR_GS_ABOVE_BRIDGE, {[]{return IsAdult && CanUse(HOOKSHOT) && AtNight && CanGetNightTimeGS;}}),
LocationAccess(ZR_NEAR_GROTTOS_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(ZR_NEAR_DOMAIN_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_ZR_MAGIC_BEAN_SALESMAN, {[]{return IsChild;}}),
LocationAccess(RC_ZR_FROGS_OCARINA_GAME, {[]{return IsChild && CanPlay(ZeldasLullaby) && CanPlay(SariasSong) && CanPlay(SunsSong) && CanPlay(EponasSong) && CanPlay(SongOfTime) && CanPlay(SongOfStorms);}}),
LocationAccess(RC_ZR_FROGS_IN_THE_RAIN, {[]{return IsChild && CanPlay(SongOfStorms);}}),
LocationAccess(RC_ZR_FROGS_ZELDAS_LULLABY, {[]{return IsChild && CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_ZR_FROGS_EPONAS_SONG, {[]{return IsChild && CanPlay(EponasSong);}}),
LocationAccess(RC_ZR_FROGS_SARIAS_SONG, {[]{return IsChild && CanPlay(SariasSong);}}),
LocationAccess(RC_ZR_FROGS_SUNS_SONG, {[]{return IsChild && CanPlay(SunsSong);}}),
LocationAccess(RC_ZR_FROGS_SONG_OF_TIME, {[]{return IsChild && CanPlay(SongOfTime);}}),
LocationAccess(RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && LogicZoraRiverLower);}}),
LocationAccess(RC_ZR_NEAR_DOMAIN_FREESTANDING_POH, {[]{return IsChild || CanUse(RG_HOVER_BOOTS) || (IsAdult && LogicZoraRiverUpper);}}),
LocationAccess(RC_ZR_GS_LADDER, {[]{return IsChild && AtNight && CanChildAttack && CanGetNightTimeGS;}}),
LocationAccess(RC_ZR_GS_NEAR_RAISED_GROTTOS, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_ZR_GS_ABOVE_BRIDGE, {[]{return IsAdult && CanUse(RG_HOOKSHOT) && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(ZR_FRONT, {[]{return true;}}),
Entrance(ZR_OPEN_GROTTO, {[]{return true;}}),
Entrance(ZR_FAIRY_GROTTO, {[]{return Here(ZORAS_RIVER, []{return CanBlastOrSmash;});}}),
Entrance(THE_LOST_WOODS, {[]{return CanDive || CanUse(IRON_BOOTS);}}),
Entrance(ZR_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
Entrance(ZR_BEHIND_WATERFALL, {[]{return CanPlay(ZeldasLullaby) || (IsChild && LogicZoraWithCucco) || (IsAdult && CanUse(HOVER_BOOTS) && LogicZoraWithHovers);}}),
Entrance(RR_ZR_FRONT, {[]{return true;}}),
Entrance(RR_ZR_OPEN_GROTTO, {[]{return true;}}),
Entrance(RR_ZR_FAIRY_GROTTO, {[]{return Here(RR_ZORAS_RIVER, []{return CanBlastOrSmash;});}}),
Entrance(RR_THE_LOST_WOODS, {[]{return CanDive || CanUse(RG_IRON_BOOTS);}}),
Entrance(RR_ZR_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return CanPlay(ZeldasLullaby) || (IsChild && LogicZoraWithCucco) || (IsAdult && CanUse(RG_HOVER_BOOTS) && LogicZoraWithHovers);}}),
});
areaTable[ZR_BEHIND_WATERFALL] = Area("ZR Behind Waterfall", "Zora River", NONE, DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_ZR_BEHIND_WATERFALL] = Area("ZR Behind Waterfall", "Zora River", RHT_NONE, DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(ZORAS_RIVER, {[]{return true;}}),
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
Entrance(RR_ZORAS_RIVER, {[]{return true;}}),
Entrance(RR_ZORAS_DOMAIN, {[]{return true;}}),
});
areaTable[ZR_OPEN_GROTTO] = Area("ZR Open Grotto", "ZR Open Grotto", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
areaTable[RR_ZR_OPEN_GROTTO] = Area("ZR Open Grotto", "ZR Open Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
//Locations
LocationAccess(ZR_OPEN_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(ZR_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_ZR_OPEN_GROTTO_CHEST, {[]{return true;}}),
LocationAccess(RC_ZR_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(ZORAS_RIVER, {[]{return true;}}),
Entrance(RR_ZORAS_RIVER, {[]{return true;}}),
});
areaTable[ZR_FAIRY_GROTTO] = Area("ZR Fairy Grotto", "ZR Fairy Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_ZR_FAIRY_GROTTO] = Area("ZR Fairy Grotto", "ZR Fairy Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Event
EventAccess(&FreeFairies, {[]{return true;}}),
}, {}, {
//Exits
Entrance(ZORAS_RIVER, {[]{return true;}}),
Entrance(RR_ZORAS_RIVER, {[]{return true;}}),
});
areaTable[ZR_STORMS_GROTTO] = Area("ZR Storms Grotto", "ZR Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_ZR_STORMS_GROTTO] = Area("ZR Storms Grotto", "ZR Storms Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(ZR_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(ZR_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
LocationAccess(RC_ZR_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
LocationAccess(RC_ZR_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
}, {
//Exits
Entrance(ZORAS_RIVER, {[]{return true;}}),
Entrance(RR_ZORAS_RIVER, {[]{return true;}}),
});
areaTable[ZORAS_DOMAIN] = Area("Zoras Domain", "Zoras Domain", ZORAS_DOMAIN, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_ZORAS_DOMAIN] = Area("Zoras Domain", "Zoras Domain", RHT_ZORAS_DOMAIN, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&EyeballFrogAccess, {[]{return EyeballFrogAccess || (IsAdult && KingZoraThawed && (Eyedrops || EyeballFrog || Prescription || PrescriptionAccess));}}),
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
@@ -91,76 +91,76 @@ void AreaTable_Init_ZorasDomain() {
EventAccess(&DeliverLetter, {[]{return DeliverLetter || (RutosLetter && IsChild && ZorasFountain.IsNot(ZORASFOUNTAIN_OPEN));}}),
}, {
//Locations
LocationAccess(ZD_DIVING_MINIGAME, {[]{return IsChild;}}),
LocationAccess(ZD_CHEST, {[]{return IsChild && CanUse(STICKS);}}),
LocationAccess(ZD_KING_ZORA_THAWED, {[]{return KingZoraThawed;}}),
LocationAccess(ZD_TRADE_PRESCRIPTION, {[]{return KingZoraThawed && Prescription;}}),
LocationAccess(ZD_GS_FROZEN_WATERFALL, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || CanUse(SLINGSHOT) || Bow || MagicMeter || LogicDomainGS) && CanGetNightTimeGS;}}),
LocationAccess(ZD_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_ZD_DIVING_MINIGAME, {[]{return IsChild;}}),
LocationAccess(RC_ZD_CHEST, {[]{return IsChild && CanUse(RG_STICKS);}}),
LocationAccess(RC_ZD_KING_ZORA_THAWED, {[]{return KingZoraThawed;}}),
LocationAccess(RC_ZD_TRADE_PRESCRIPTION, {[]{return KingZoraThawed && Prescription;}}),
LocationAccess(RC_ZD_GS_FROZEN_WATERFALL, {[]{return IsAdult && AtNight && (HookshotOrBoomerang || CanUse(RG_FAIRY_SLINGSHOT) || Bow || MagicMeter || LogicDomainGS) && CanGetNightTimeGS;}}),
LocationAccess(RC_ZD_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(ZR_BEHIND_WATERFALL, {[]{return true;}}),
Entrance(LAKE_HYLIA, {[]{return IsChild && (CanDive || CanUse(IRON_BOOTS));}}),
Entrance(ZD_BEHIND_KING_ZORA, {[]{return DeliverLetter || ZorasFountain.Is(ZORASFOUNTAIN_OPEN) || (ZorasFountain.Is(ZORASFOUNTAIN_ADULT) && IsAdult) || (LogicKingZoraSkip && IsAdult);}}),
Entrance(ZD_SHOP, {[]{return IsChild || BlueFire;}}),
Entrance(ZD_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
Entrance(RR_ZR_BEHIND_WATERFALL, {[]{return true;}}),
Entrance(RR_LAKE_HYLIA, {[]{return IsChild && (CanDive || CanUse(RG_IRON_BOOTS));}}),
Entrance(RR_ZD_BEHIND_KING_ZORA, {[]{return DeliverLetter || ZorasFountain.Is(ZORASFOUNTAIN_OPEN) || (ZorasFountain.Is(ZORASFOUNTAIN_ADULT) && IsAdult) || (LogicKingZoraSkip && IsAdult);}}),
Entrance(RR_ZD_SHOP, {[]{return IsChild || BlueFire;}}),
Entrance(RR_ZD_STORMS_GROTTO, {[]{return CanOpenStormGrotto;}}),
});
areaTable[ZD_BEHIND_KING_ZORA] = Area("ZD Behind King Zora", "Zoras Domain", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_ZD_BEHIND_KING_ZORA] = Area("ZD Behind King Zora", "Zoras Domain", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(ZORAS_DOMAIN, {[]{return DeliverLetter || ZorasFountain.Is(ZORASFOUNTAIN_OPEN) || (ZorasFountain.Is(ZORASFOUNTAIN_ADULT) && IsAdult);}}),
Entrance(ZORAS_FOUNTAIN, {[]{return true;}}),
Entrance(RR_ZORAS_DOMAIN, {[]{return DeliverLetter || ZorasFountain.Is(ZORASFOUNTAIN_OPEN) || (ZorasFountain.Is(ZORASFOUNTAIN_ADULT) && IsAdult);}}),
Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}),
});
areaTable[ZD_SHOP] = Area("ZD Shop", "ZD Shop", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_ZD_SHOP] = Area("ZD Shop", "ZD Shop", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(ZD_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(ZD_SHOP_ITEM_2, {[]{return true;}}),
LocationAccess(ZD_SHOP_ITEM_3, {[]{return true;}}),
LocationAccess(ZD_SHOP_ITEM_4, {[]{return true;}}),
LocationAccess(ZD_SHOP_ITEM_5, {[]{return true;}}),
LocationAccess(ZD_SHOP_ITEM_6, {[]{return true;}}),
LocationAccess(ZD_SHOP_ITEM_7, {[]{return true;}}),
LocationAccess(ZD_SHOP_ITEM_8, {[]{return true;}}),
LocationAccess(RC_ZD_SHOP_ITEM_1, {[]{return true;}}),
LocationAccess(RC_ZD_SHOP_ITEM_2, {[]{return true;}}),
LocationAccess(RC_ZD_SHOP_ITEM_3, {[]{return true;}}),
LocationAccess(RC_ZD_SHOP_ITEM_4, {[]{return true;}}),
LocationAccess(RC_ZD_SHOP_ITEM_5, {[]{return true;}}),
LocationAccess(RC_ZD_SHOP_ITEM_6, {[]{return true;}}),
LocationAccess(RC_ZD_SHOP_ITEM_7, {[]{return true;}}),
LocationAccess(RC_ZD_SHOP_ITEM_8, {[]{return true;}}),
}, {
//Exits
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
Entrance(RR_ZORAS_DOMAIN, {[]{return true;}}),
});
areaTable[ZD_STORMS_GROTTO] = Area("ZD Storms Grotto", "ZD Storms Grotto", NONE, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_ZD_STORMS_GROTTO] = Area("ZD Storms Grotto", "ZD Storms Grotto", RHT_NONE, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&FreeFairies, {[]{return true;}}),
}, {}, {
//Exits
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
Entrance(RR_ZORAS_DOMAIN, {[]{return true;}}),
});
areaTable[ZORAS_FOUNTAIN] = Area("Zoras Fountain", "Zoras Fountain", ZORAS_FOUNTAIN, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_ZORAS_FOUNTAIN] = Area("Zoras Fountain", "Zoras Fountain", RHT_ZORAS_FOUNTAIN, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || (CanUse(STICKS) && AtDay);}}),
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || (CanUse(RG_STICKS) && AtDay);}}),
}, {
//Locations
LocationAccess(ZF_ICEBERG_FREESTANDING_POH, {[]{return IsAdult;}}),
LocationAccess(ZF_BOTTOM_FREESTANDING_POH, {[]{return IsAdult && IronBoots && WaterTimer >= 24;}}),
LocationAccess(ZF_GS_TREE, {[]{return IsChild;}}),
LocationAccess(ZF_GS_ABOVE_THE_LOG, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(ZF_GS_HIDDEN_CAVE, {[]{return CanUse(SILVER_GAUNTLETS) && CanBlastOrSmash && HookshotOrBoomerang && IsAdult && AtNight && CanGetNightTimeGS;}}),
LocationAccess(ZF_FAIRY_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(ZF_JABU_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_ZF_ICEBERC_FREESTANDING_POH, {[]{return IsAdult;}}),
LocationAccess(RC_ZF_BOTTOM_FREESTANDING_POH, {[]{return IsAdult && IronBoots && WaterTimer >= 24;}}),
LocationAccess(RC_ZF_GS_TREE, {[]{return IsChild;}}),
LocationAccess(RC_ZF_GS_ABOVE_THE_LOG, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_ZF_GS_HIDDEN_CAVE, {[]{return CanUse(RG_SILVER_GAUNTLETS) && CanBlastOrSmash && HookshotOrBoomerang && IsAdult && AtNight && CanGetNightTimeGS;}}),
LocationAccess(RC_FAIRY_GOSSIP_STONE, {[]{return true;}}),
LocationAccess(RC_JABU_GOSSIP_STONE, {[]{return true;}}),
}, {
//Exits
Entrance(ZD_BEHIND_KING_ZORA, {[]{return true;}}),
Entrance(JABU_JABUS_BELLY_ENTRYWAY, {[]{return (IsChild && Fish);}}),
Entrance(ICE_CAVERN_ENTRYWAY, {[]{return IsAdult;}}),
Entrance(ZF_GREAT_FAIRY_FOUNTAIN, {[]{return HasExplosives;}}),
Entrance(RR_ZD_BEHIND_KING_ZORA, {[]{return true;}}),
Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, {[]{return (IsChild && Fish);}}),
Entrance(RR_ICE_CAVERN_ENTRYWAY, {[]{return IsAdult;}}),
Entrance(RR_ZF_GREAT_FAIRY_FOUNTAIN, {[]{return HasExplosives;}}),
});
areaTable[ZF_GREAT_FAIRY_FOUNTAIN] = Area("ZF Great Fairy Fountain", "ZF Great Fairy Fountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_ZF_GREAT_FAIRY_FOUNTAIN] = Area("ZF Great Fairy Fountain", "ZF Great Fairy Fountain", RHT_NONE, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LocationAccess(ZF_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
LocationAccess(RC_ZF_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);}}),
}, {
//Exits
Entrance(ZORAS_FOUNTAIN, {[]{return true;}}),
Entrance(RR_ZORAS_FOUNTAIN, {[]{return true;}}),
});
}

View File

@@ -385,84 +385,84 @@ namespace Logic {
return Ocarina && song;
}
static bool IsMagicItem(uint32_t item) {
return item == DINS_FIRE ||
item == FARORES_WIND ||
item == NAYRUS_LOVE ||
item == LENS_OF_TRUTH;
static bool IsMagicItem(RandomizerGet item) {
return item == RG_DINS_FIRE ||
item == RG_FARORES_WIND ||
item == RG_NAYRUS_LOVE ||
item == RG_LENS_OF_TRUTH;
}
static bool IsMagicArrow(uint32_t item) {
return item == FIRE_ARROWS ||
item == ICE_ARROWS ||
item == LIGHT_ARROWS;
static bool IsMagicArrow(RandomizerGet item) {
return item == RG_FIRE_ARROWS ||
item == RG_ICE_ARROWS ||
item == RG_LIGHT_ARROWS;
}
bool HasItem(uint32_t itemName) {
return (itemName == DINS_FIRE && DinsFire) ||
(itemName == FARORES_WIND && FaroresWind) ||
(itemName == NAYRUS_LOVE && NayrusLove) ||
(itemName == LENS_OF_TRUTH && LensOfTruth) ||
(itemName == BOW && Bow) ||
(itemName == MEGATON_HAMMER && Hammer) ||
(itemName == IRON_BOOTS && IronBoots) ||
(itemName == HOVER_BOOTS && HoverBoots) ||
(itemName == HOOKSHOT && Hookshot) ||
(itemName == LONGSHOT && Longshot) ||
(itemName == SILVER_GAUNTLETS && SilverGauntlets) ||
(itemName == GOLDEN_GAUNTLETS && GoldenGauntlets) ||
(itemName == GORON_TUNIC && GoronTunic) ||
(itemName == ZORA_TUNIC && ZoraTunic) ||
(itemName == SCARECROW && Scarecrow) ||
(itemName == DISTANT_SCARECROW && DistantScarecrow)||
(itemName == HYLIAN_SHIELD && HylianShield) ||
(itemName == MIRROR_SHIELD && MirrorShield) ||
(itemName == MASTER_SWORD && MasterSword) ||
(itemName == BIGGORON_SWORD && BiggoronSword) ||
(itemName == SLINGSHOT && Slingshot) ||
(itemName == BOOMERANG && Boomerang) ||
(itemName == KOKIRI_SWORD && KokiriSword) ||
(itemName == STICKS && Sticks) ||
(itemName == DEKU_SHIELD && DekuShield) ||
(itemName == FIRE_ARROWS && FireArrows) ||
(itemName == ICE_ARROWS && IceArrows) ||
(itemName == LIGHT_ARROWS && LightArrows);
bool HasItem(RandomizerGet itemName) {
return (itemName == RG_DINS_FIRE && DinsFire) ||
(itemName == RG_FARORES_WIND && FaroresWind) ||
(itemName == RG_NAYRUS_LOVE && NayrusLove) ||
(itemName == RG_LENS_OF_TRUTH && LensOfTruth) ||
(itemName == RG_FAIRY_BOW && Bow) ||
(itemName == RG_MEGATON_HAMMER && Hammer) ||
(itemName == RG_IRON_BOOTS && IronBoots) ||
(itemName == RG_HOVER_BOOTS && HoverBoots) ||
(itemName == RG_HOOKSHOT && Hookshot) ||
(itemName == RG_LONGSHOT && Longshot) ||
(itemName == RG_SILVER_GAUNTLETS && SilverGauntlets) ||
(itemName == RG_GOLDEN_GAUNTLETS && GoldenGauntlets) ||
(itemName == RG_GORON_TUNIC && GoronTunic) ||
(itemName == RG_ZORA_TUNIC && ZoraTunic) ||
(itemName == RG_SCARECROW && Scarecrow) ||
(itemName == RG_DISTANT_SCARECROW && DistantScarecrow)||
(itemName == RG_HYLIAN_SHIELD && HylianShield) ||
(itemName == RG_MIRROR_SHIELD && MirrorShield) ||
(itemName == RG_MASTER_SWORD && MasterSword) ||
(itemName == RG_BIGGORON_SWORD && BiggoronSword) ||
(itemName == RG_FAIRY_SLINGSHOT && Slingshot) ||
(itemName == RG_BOOMERANG && Boomerang) ||
(itemName == RG_KOKIRI_SWORD && KokiriSword) ||
(itemName == RG_STICKS && Sticks) ||
(itemName == RG_DEKU_SHIELD && DekuShield) ||
(itemName == RG_FIRE_ARROWS && FireArrows) ||
(itemName == RG_ICE_ARROWS && IceArrows) ||
(itemName == RG_LIGHT_ARROWS && LightArrows);
}
//Can the passed in item be used?
bool CanUse(uint32_t itemName) {
bool CanUse(RandomizerGet itemName) {
if (!HasItem(itemName))
return false;
switch (itemName) {
// Adult items
case BOW: return IsAdult || BowAsChild;
case MEGATON_HAMMER: return IsAdult || HammerAsChild;
case IRON_BOOTS: return IsAdult || IronBootsAsChild;
case HOVER_BOOTS: return IsAdult || HoverBootsAsChild;
case HOOKSHOT: return IsAdult || HookshotAsChild;
case LONGSHOT: return IsAdult || HookshotAsChild;
case SILVER_GAUNTLETS: return IsAdult;
case GOLDEN_GAUNTLETS: return IsAdult;
case GORON_TUNIC: return IsAdult || GoronTunicAsChild;
case ZORA_TUNIC: return IsAdult || ZoraTunicAsChild;
case SCARECROW: return IsAdult || HookshotAsChild;
case DISTANT_SCARECROW: return IsAdult || HookshotAsChild;
case HYLIAN_SHIELD: return IsAdult;
case MIRROR_SHIELD: return IsAdult || MirrorShieldAsChild;
case MASTER_SWORD: return IsAdult || MasterSwordAsChild;
case BIGGORON_SWORD: return IsAdult || BiggoronSwordAsChild;
case RG_FAIRY_BOW: return IsAdult || BowAsChild;
case RG_MEGATON_HAMMER: return IsAdult || HammerAsChild;
case RG_IRON_BOOTS: return IsAdult || IronBootsAsChild;
case RG_HOVER_BOOTS: return IsAdult || HoverBootsAsChild;
case RG_HOOKSHOT: return IsAdult || HookshotAsChild;
case RG_LONGSHOT: return IsAdult || HookshotAsChild;
case RG_SILVER_GAUNTLETS: return IsAdult;
case RG_GOLDEN_GAUNTLETS: return IsAdult;
case RG_GORON_TUNIC: return IsAdult || GoronTunicAsChild;
case RG_ZORA_TUNIC: return IsAdult || ZoraTunicAsChild;
case RG_SCARECROW: return IsAdult || HookshotAsChild;
case RG_DISTANT_SCARECROW: return IsAdult || HookshotAsChild;
case RG_HYLIAN_SHIELD: return IsAdult;
case RG_MIRROR_SHIELD: return IsAdult || MirrorShieldAsChild;
case RG_MASTER_SWORD: return IsAdult || MasterSwordAsChild;
case RG_BIGGORON_SWORD: return IsAdult || BiggoronSwordAsChild;
// Child items
case SLINGSHOT: return IsChild || SlingshotAsAdult;
case BOOMERANG: return IsChild || BoomerangAsAdult;
case KOKIRI_SWORD: return IsChild || KokiriSwordAsAdult;
case STICKS: return IsChild || StickAsAdult;
case DEKU_SHIELD: return IsChild || DekuShieldAsAdult;
case RG_FAIRY_SLINGSHOT: return IsChild || SlingshotAsAdult;
case RG_BOOMERANG: return IsChild || BoomerangAsAdult;
case RG_KOKIRI_SWORD: return IsChild || KokiriSwordAsAdult;
case RG_STICKS: return IsChild || StickAsAdult;
case RG_DEKU_SHIELD: return IsChild || DekuShieldAsAdult;
// Magic items
default: return MagicMeter && (IsMagicItem(itemName) || (IsMagicArrow(itemName) && CanUse(BOW)));
default: return MagicMeter && (IsMagicItem(itemName) || (IsMagicArrow(itemName) && CanUse(RG_FAIRY_BOW)));
}
}
@@ -499,7 +499,7 @@ namespace Logic {
//todo rewrite glitch section
bool CanEquipSwap(uint32_t itemName) {
bool CanEquipSwap(RandomizerGet itemName) {
if (!HasItem(itemName))
return false;
@@ -512,9 +512,9 @@ namespace Logic {
bool CanDoGlitch(GlitchType glitch) {
switch(glitch) {
case GlitchType::EquipSwapDins:
return ((IsAdult && HasItem(DINS_FIRE)) || (IsChild && (HasItem(STICKS) || HasItem(DINS_FIRE)))) && GlitchEquipSwapDins;
return ((IsAdult && HasItem(RG_DINS_FIRE)) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_DINS_FIRE)))) && GlitchEquipSwapDins;
case GlitchType::EquipSwap: // todo: add bunny hood to adult item equippable list and child trade item to child item equippable list
return ((IsAdult && (HasItem(DINS_FIRE) || HasItem(FARORES_WIND) || HasItem(NAYRUS_LOVE))) || (IsChild && (HasItem(STICKS) || HasItem(SLINGSHOT) || HasItem(BOOMERANG) || HasBottle || Nuts || Ocarina || HasItem(LENS_OF_TRUTH) || HasExplosives || (MagicBean || MagicBeanPack) || HasItem(DINS_FIRE) || HasItem(FARORES_WIND) || HasItem(NAYRUS_LOVE)))) && GlitchEquipSwap;
return ((IsAdult && (HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE))) || (IsChild && (HasItem(RG_STICKS) || HasItem(RG_FAIRY_SLINGSHOT) || HasItem(RG_BOOMERANG) || HasBottle || Nuts || Ocarina || HasItem(RG_LENS_OF_TRUTH) || HasExplosives || (MagicBean || MagicBeanPack) || HasItem(RG_DINS_FIRE) || HasItem(RG_FARORES_WIND) || HasItem(RG_NAYRUS_LOVE)))) && GlitchEquipSwap;
}
//Shouldn't be reached
@@ -559,7 +559,7 @@ namespace Logic {
Nuts = DekuNutDrop || Nuts;
Sticks = DekuStickDrop || Sticks;
Bugs = HasBottle && BugsAccess;
BlueFire = (HasBottle && BlueFireAccess) || (BlueFireArrows && CanUse(ICE_ARROWS));
BlueFire = (HasBottle && BlueFireAccess) || (BlueFireArrows && CanUse(RG_ICE_ARROWS));
Fish = HasBottle && FishAccess;
Fairy = HasBottle && FairyAccess;
@@ -585,11 +585,11 @@ namespace Logic {
// IsChild = Age == AGE_CHILD;
// IsAdult = Age == AGE_ADULT;
CanBlastOrSmash = HasExplosives || CanUse(MEGATON_HAMMER);
CanChildAttack = IsChild && (Slingshot || Boomerang || Sticks || KokiriSword || HasExplosives || CanUse(DINS_FIRE) || CanUse(MASTER_SWORD) || CanUse(MEGATON_HAMMER) || CanUse(BIGGORON_SWORD));
CanChildDamage = IsChild && (Slingshot || Sticks || KokiriSword || HasExplosives || CanUse(DINS_FIRE) || CanUse(MASTER_SWORD) || CanUse(MEGATON_HAMMER) || CanUse(BIGGORON_SWORD));
CanBlastOrSmash = HasExplosives || CanUse(RG_MEGATON_HAMMER);
CanChildAttack = IsChild && (Slingshot || Boomerang || Sticks || KokiriSword || HasExplosives || CanUse(RG_DINS_FIRE) || CanUse(RG_MASTER_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_BIGGORON_SWORD));
CanChildDamage = IsChild && (Slingshot || Sticks || KokiriSword || HasExplosives || CanUse(RG_DINS_FIRE) || CanUse(RG_MASTER_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_BIGGORON_SWORD));
CanStunDeku = IsAdult || CanChildAttack || Nuts || HasShield;
CanCutShrubs = IsAdult /*|| Sticks*/ || KokiriSword || Boomerang || HasExplosives || CanUse(MASTER_SWORD) || CanUse(MEGATON_HAMMER) || CanUse(BIGGORON_SWORD);
CanCutShrubs = IsAdult /*|| Sticks*/ || KokiriSword || Boomerang || HasExplosives || CanUse(RG_MASTER_SWORD) || CanUse(RG_MEGATON_HAMMER) || CanUse(RG_BIGGORON_SWORD);
CanDive = ProgressiveScale >= 1;
CanLeaveForest = OpenForest.IsNot(OPENFOREST_CLOSED) || IsAdult || DekuTreeClear || ShuffleInteriorEntrances || ShuffleOverworldEntrances;
CanPlantBugs = IsChild && Bugs;
@@ -598,37 +598,37 @@ namespace Logic {
CanSummonGossipFairyWithoutSuns = Ocarina && (ZeldasLullaby || EponasSong || SongOfTime);
Hearts = BaseHearts + HeartContainer + (PieceOfHeart >> 2);
EffectiveHealth = ((Hearts << (2 + DoubleDefense)) >> Multiplier) + ((Hearts << (2 + DoubleDefense)) % (1 << Multiplier) > 0); //Number of half heart hits to die, ranges from 1 to 160
FireTimer = CanUse(GORON_TUNIC) ? 255 : (LogicFewerTunicRequirements) ? (Hearts * 8) : 0;
WaterTimer = CanUse( ZORA_TUNIC) ? 255 : (LogicFewerTunicRequirements) ? (Hearts * 8) : 0;
FireTimer = CanUse(RG_GORON_TUNIC) ? 255 : (LogicFewerTunicRequirements) ? (Hearts * 8) : 0;
WaterTimer = CanUse(RG_ZORA_TUNIC) ? 255 : (LogicFewerTunicRequirements) ? (Hearts * 8) : 0;
NeedNayrusLove = (EffectiveHealth == 1);
CanSurviveDamage = !NeedNayrusLove || CanUse(NAYRUS_LOVE);
CanSurviveDamage = !NeedNayrusLove || CanUse(RG_NAYRUS_LOVE);
CanTakeDamage = Fairy || CanSurviveDamage;
CanTakeDamageTwice = (Fairy && NumBottles >= 2) || ((EffectiveHealth == 2) && (CanUse(NAYRUS_LOVE) || Fairy)) || (EffectiveHealth > 2);
CanTakeDamageTwice = (Fairy && NumBottles >= 2) || ((EffectiveHealth == 2) && (CanUse(RG_NAYRUS_LOVE) || Fairy)) || (EffectiveHealth > 2);
//CanPlantBean = IsChild && (MagicBean || MagicBeanPack);
CanOpenBombGrotto = CanBlastOrSmash && (ShardOfAgony || LogicGrottosWithoutAgony);
CanOpenStormGrotto = CanPlay(SongOfStorms) && (ShardOfAgony || LogicGrottosWithoutAgony);
HookshotOrBoomerang = CanUse(HOOKSHOT) || CanUse(BOOMERANG);
HookshotOrBoomerang = CanUse(RG_HOOKSHOT) || CanUse(RG_BOOMERANG);
CanGetNightTimeGS = (CanPlay(SunsSong) || !NightGSExpectSuns);
GuaranteeTradePath = ShuffleInteriorEntrances || ShuffleOverworldEntrances || LogicBiggoronBolero || CanBlastOrSmash || StopGCRollingGoronAsAdult;
//GuaranteeHint = (hints == "Mask" && MaskofTruth) || (hints == "Agony") || (hints != "Mask" && hints != "Agony");
HasFireSource = CanUse(DINS_FIRE) || CanUse(FIRE_ARROWS);
HasFireSourceWithTorch = HasFireSource || CanUse(STICKS);
HasFireSource = CanUse(RG_DINS_FIRE) || CanUse(RG_FIRE_ARROWS);
HasFireSourceWithTorch = HasFireSource || CanUse(RG_STICKS);
//Gerudo Fortress
CanFinishGerudoFortress = (GerudoFortress.Is(GERUDOFORTRESS_NORMAL) && GerudoFortressKeys >= 4 && (IsAdult || KokiriSword || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen)) ||
(GerudoFortress.Is(GERUDOFORTRESS_FAST) && GerudoFortressKeys >= 1 && (IsAdult || KokiriSword || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD))) ||
CanFinishGerudoFortress = (GerudoFortress.Is(GERUDOFORTRESS_NORMAL) && GerudoFortressKeys >= 4 && (IsAdult || KokiriSword || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) && (GerudoToken || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_HOVER_BOOTS) || LogicGerudoKitchen)) ||
(GerudoFortress.Is(GERUDOFORTRESS_FAST) && GerudoFortressKeys >= 1 && (IsAdult || KokiriSword || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD))) ||
(GerudoFortress.IsNot(GERUDOFORTRESS_NORMAL) && GerudoFortress.IsNot(GERUDOFORTRESS_FAST));
HasShield = CanUse(HYLIAN_SHIELD) || CanUse(DEKU_SHIELD); //Mirror shield can't reflect attacks
CanShield = CanUse(MIRROR_SHIELD) || HasShield;
ChildShield = IsChild && CanUse(DEKU_SHIELD); //hylian shield is not helpful for child
AdultReflectShield = IsAdult && CanUse(HYLIAN_SHIELD); //Mirror shield can't reflect attacks
AdultShield = IsAdult && (CanUse(HYLIAN_SHIELD) || CanUse(MIRROR_SHIELD));
HasShield = CanUse(RG_HYLIAN_SHIELD) || CanUse(RG_DEKU_SHIELD); //Mirror shield can't reflect attacks
CanShield = CanUse(RG_MIRROR_SHIELD) || HasShield;
ChildShield = IsChild && CanUse(RG_DEKU_SHIELD); //hylian shield is not helpful for child
AdultReflectShield = IsAdult && CanUse(RG_HYLIAN_SHIELD); //Mirror shield can't reflect attacks
AdultShield = IsAdult && (CanUse(RG_HYLIAN_SHIELD) || CanUse(RG_MIRROR_SHIELD));
CanShieldFlick = ChildShield || AdultShield;
CanJumpslash = IsAdult || Sticks || KokiriSword;
CanUseProjectile = HasExplosives || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(SLINGSHOT) || CanUse(BOOMERANG);
CanUseMagicArrow = CanUse(FIRE_ARROWS) || CanUse(ICE_ARROWS) || CanUse(LIGHT_ARROWS);
CanUseProjectile = HasExplosives || CanUse(RG_FAIRY_BOW) || CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_BOOMERANG);
CanUseMagicArrow = CanUse(RG_FIRE_ARROWS) || CanUse(RG_ICE_ARROWS) || CanUse(RG_LIGHT_ARROWS);
//Bridge and LACS Requirements
MedallionCount = (ForestMedallion ? 1:0) + (FireMedallion ? 1:0) + (WaterMedallion ? 1:0) + (SpiritMedallion ? 1:0) + (ShadowMedallion ? 1:0) + (LightMedallion ? 1:0);
@@ -657,62 +657,62 @@ namespace Logic {
}
bool SmallKeys(Key dungeon, uint8_t requiredAmount) {
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount) {
return SmallKeys(dungeon, requiredAmount, requiredAmount);
}
bool SmallKeys(Key dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched) {
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched) {
switch (dungeon) {
case FOREST_TEMPLE:
case RR_FOREST_TEMPLE:
/*if (IsGlitched && (GetDifficultyValueFromString(GlitchHookshotJump_Boots) >= static_cast<uint8_t>(GlitchDifficulty::INTERMEDIATE) || GetDifficultyValueFromString(GlitchHoverBoost) >= static_cast<uint8_t>(GlitchDifficulty::NOVICE) ||
(GetDifficultyValueFromString(GlitchHover) >= static_cast<uint8_t>(GlitchDifficulty::NOVICE) && GetDifficultyValueFromString(GlitchISG) >= static_cast<uint8_t>(GlitchDifficulty::INTERMEDIATE)))) {
return ForestTempleKeys >= requiredAmountGlitched;
}*/
return ForestTempleKeys >= requiredAmountGlitchless;
case FIRE_TEMPLE:
case RR_FIRE_TEMPLE:
/*if (IsGlitched && (GetDifficultyValueFromString(GlitchLedgeClip) >= static_cast<uint8_t>(GlitchDifficulty::INTERMEDIATE) || GetDifficultyValueFromString(GlitchHover) >= static_cast<uint8_t>(GlitchDifficulty::INTERMEDIATE))) {
return FireTempleKeys >= requiredAmountGlitched;
}*/
return FireTempleKeys >= requiredAmountGlitchless;
case WATER_TEMPLE:
case RR_WATER_TEMPLE:
/*if (IsGlitched && (false)) {
return WaterTempleKeys >= requiredAmountGlitched;
}*/
return WaterTempleKeys >= requiredAmountGlitchless;
case SPIRIT_TEMPLE:
case RR_SPIRIT_TEMPLE:
/*if (IsGlitched && (false)) {
return SpiritTempleKeys >= requiredAmountGlitched;
}*/
return SpiritTempleKeys >= requiredAmountGlitchless;
case SHADOW_TEMPLE:
case RR_SHADOW_TEMPLE:
/*if (IsGlitched && (GetDifficultyValueFromString(GlitchHookshotClip) >= static_cast<uint8_t>(GlitchDifficulty::NOVICE))) {
return ShadowTempleKeys >= requiredAmountGlitched;
}*/
return ShadowTempleKeys >= requiredAmountGlitchless;
case BOTTOM_OF_THE_WELL:
case RR_BOTTOM_OF_THE_WELL:
/*if (IsGlitched && (false)) {
return BottomOfTheWellKeys >= requiredAmountGlitched;
}*/
return BottomOfTheWellKeys >= requiredAmountGlitchless;
case GERUDO_TRAINING_GROUNDS:
case RR_GERUDO_TRAINING_GROUNDS:
/*if (IsGlitched && (false)) {
return GerudoTrainingGroundsKeys >= requiredAmountGlitched;
}*/
return GerudoTrainingGroundsKeys >= requiredAmountGlitchless;
case GANONS_CASTLE:
case RR_GANONS_CASTLE:
/*if (IsGlitched && (false)) {
return GanonsCastleKeys >= requiredAmountGlitched;
}*/
return GanonsCastleKeys >= requiredAmountGlitchless;
case MARKET_TREASURE_CHEST_GAME:
case RR_MARKET_TREASURE_CHEST_GAME:
/*if (IsGlitched && (false)) {
return TreasureGameKeys >= requiredAmountGlitched;
}*/

View File

@@ -1,6 +1,6 @@
#pragma once
#include "keys.hpp"
#include "../randomizerTypes.h"
#include <cstdint>
namespace Logic {
@@ -375,11 +375,10 @@ enum class GlitchDifficulty {
void UpdateHelpers();
bool CanPlay(bool song);
bool CanUse(uint32_t itemName);
bool CanUse(RandomizerGet itemName);
bool HasProjectile(HasProjectileAge age);
bool HasBossSoul(uint32_t itemName);
bool SmallKeys(Key dungeon, uint8_t requiredAmount);
bool SmallKeys(Key dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched);
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount);
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched);
bool CanDoGlitch(GlitchType glitch);
bool EventsUpdated();
void LogicReset();

View File

@@ -13,16 +13,16 @@
#define DELETE_PRESET 6
#define RESET_TO_DEFAULTS 8
#define RESET "\x1b[0m"
#define DIM "\x1b[2m"
// #define RESET "\x1b[0m"
// #define DIM "\x1b[2m"
#define BLACK "\x1b[30m"
#define RED "\x1b[31m"
#define GREEN "\x1b[32m"
#define YELLOW "\x1b[33m"
#define BLUE "\x1b[34m"
#define MEGANTA "\x1b[35m"
#define CYAN "\x1b[36m"
#define WHITE "\x1b[37m"
// #define BLACK "\x1b[30m"
// #define RED "\x1b[31m"
// #define GREEN "\x1b[32m"
// #define YELLOW "\x1b[33m"
// #define BLUE "\x1b[34m"
// #define MEGANTA "\x1b[35m"
// #define CYAN "\x1b[36m"
// #define WHITE "\x1b[37m"
std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSetting, std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks, std::string seedInput);

View File

@@ -16,10 +16,11 @@ int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uin
// resolved to something random
Random_Init(seed);
overrides.clear();
auto ctx = Rando::Context::GetInstance();
ctx->overrides.clear();
CustomMessages::ClearMessages();
ItemReset();
HintReset();
ctx->ItemReset();
ctx->HintReset();
Areas::AccessReset();
Settings::UpdateSettings(cvarSettings, excludedLocations, enabledTricks);
@@ -75,9 +76,9 @@ int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uin
#endif
}
playthroughLocations.clear();
wothLocations.clear();
playthroughBeatable = false;
ctx->playthroughLocations.clear();
ctx->wothLocations.clear();
ctx->playthroughBeatable = false;
return 1;
}

View File

@@ -1,7 +1,7 @@
#pragma once
#include <string>
#include <set>
#include "item_location.hpp"
#include "../context.h"
namespace Playthrough {
int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks);

View File

@@ -1,7 +1,7 @@
#include "menu.hpp"
#include "hint_list.hpp"
#include "item_list.hpp"
#include "item_location.hpp"
#include "../static_data.h"
#include "../item_location.h"
#include "location_access.hpp"
#include "rando_main.hpp"
// #include <soh/Enhancements/randomizer.h>
@@ -12,8 +12,6 @@
void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarSettings, std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks,
std::string seedString) {
HintTable_Init();
ItemTable_Init();
LocationTable_Init();
// std::string settingsFileName = "./randomizer/latest_settings.json";
// CVarSetString("gLoadedPreset", settingsFileName.c_str());
@@ -24,10 +22,4 @@ void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarS
CVarSave();
CVarLoad();
CVarSetInteger("gNewSeedGenerated", 1);
}
std::array<Item, KEY_ENUM_MAX>* RandoMain::GetFullItemTable() {
ItemTable_Init();
return GetFullItemTable_();
}
}

View File

@@ -1,8 +1,5 @@
#pragma once
#include "item.hpp"
#include "soh/Enhancements/randomizer/item.h"
namespace RandoMain {
void GenerateRando(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks, std::string seedInput);
std::array<Item, KEY_ENUM_MAX>* GetFullItemTable();
}

View File

@@ -2,11 +2,11 @@
#include "dungeon.hpp"
#include "fill.hpp"
#include "item_location.hpp"
#include "../context.h"
#include "../item_location.h"
#include "random.hpp"
#include "randomizer.hpp"
#include "trial.hpp"
#include "keys.hpp"
using namespace Dungeon;
using namespace Trial;
@@ -1510,17 +1510,19 @@ namespace Settings {
}
//Include and Lock the desired locations
static void IncludeAndHide(std::vector<uint32_t> locations) {
for (uint32_t loc : locations) {
Location(loc)->GetExcludedOption()->SetSelectedIndex(INCLUDE);
Location(loc)->GetExcludedOption()->Hide();
static void IncludeAndHide(std::vector<RandomizerCheck> locations) {
auto ctx = Rando::Context::GetInstance();
for (RandomizerCheck loc : locations) {
ctx->GetItemLocation(loc)->GetExcludedOption()->SetSelectedIndex(INCLUDE);
ctx->GetItemLocation(loc)->GetExcludedOption()->Hide();
}
}
//Unlock the desired locations
static void Unhide(std::vector<uint32_t> locations) {
for (uint32_t loc : locations) {
Location(loc)->GetExcludedOption()->Unhide();
static void Unhide(std::vector<RandomizerCheck> locations) {
auto ctx = Rando::Context::GetInstance();
for (RandomizerCheck loc : locations) {
ctx->GetItemLocation(loc)->GetExcludedOption()->Unhide();
}
}
@@ -1554,200 +1556,216 @@ namespace Settings {
//menu if the player's current settings would require non-junk to be placed
//at those locations. Excluded locations will have junk placed at them.
void ResolveExcludedLocationConflicts() {
auto ctx = Rando::Context::GetInstance();
std::vector<RandomizerCheck> shopLocations = ctx->GetLocations(ctx->everyPossibleLocation, Category::cShop);
// For now, just always hide shop locations, as not sure how to handle hiding them-
// 1-4 should always be hidden, while the others should be settings dependent, but random shopsanity makes that
// more complicated... Excluded shop locations are also wonky
IncludeAndHide(shopLocations);
std::vector<uint32_t> shopLocations = GetLocations(everyPossibleLocation, Category::cShop);
//For now, just always hide shop locations, as not sure how to handle hiding them-
//1-4 should always be hidden, while the others should be settings dependent, but random shopsanity makes that more complicated...
//Excluded shop locations are also wonky
IncludeAndHide(shopLocations);
// Force include song locations
std::vector<RandomizerCheck> songLocations = ctx->GetLocations(ctx->everyPossibleLocation, Category::cSong);
std::vector<RandomizerCheck> songDungeonRewards =
ctx->GetLocations(ctx->everyPossibleLocation, Category::cSongDungeonReward);
//Force include song locations
std::vector<uint32_t> songLocations = GetLocations(everyPossibleLocation, Category::cSong);
std::vector<uint32_t> songDungeonRewards = GetLocations(everyPossibleLocation, Category::cSongDungeonReward);
// Unhide all song locations, then lock necessary ones
Unhide(songLocations);
Unhide(songDungeonRewards);
//Unhide all song locations, then lock necessary ones
Unhide(songLocations);
Unhide(songDungeonRewards);
if (ShuffleSongs.Is(SONGSHUFFLE_SONG_LOCATIONS)) {
IncludeAndHide(songLocations);
} else if (ShuffleSongs.Is(SONGSHUFFLE_DUNGEON_REWARDS)) {
IncludeAndHide(songDungeonRewards);
}
//Force Include Vanilla Skulltula locations
std::vector<uint32_t> skulltulaLocations = GetLocations(everyPossibleLocation, Category::cSkulltula);
Unhide(skulltulaLocations);
if (Tokensanity.IsNot(TOKENSANITY_ALL_TOKENS)) {
if (Tokensanity.Is(TOKENSANITY_OVERWORLD)) {
//filter overworld skulls so we're just left with dungeons
FilterAndEraseFromPool(skulltulaLocations, [](const uint32_t loc){return Location(loc)->GetScene() >= 0x0A;});
} else if (Tokensanity.Is(TOKENSANITY_DUNGEONS)) {
//filter dungeon skulls so we're just left with overworld
FilterAndEraseFromPool(skulltulaLocations, [](const uint32_t loc){return Location(loc)->GetScene() < 0x0A;});
if (ShuffleSongs.Is(SONGSHUFFLE_SONG_LOCATIONS)) {
IncludeAndHide(songLocations);
} else if (ShuffleSongs.Is(SONGSHUFFLE_DUNGEON_REWARDS)) {
IncludeAndHide(songDungeonRewards);
}
IncludeAndHide(skulltulaLocations);
}
//Force Include scrubs if Scrubsanity is Off
std::vector<uint32_t> scrubLocations = GetLocations(everyPossibleLocation, Category::cDekuScrub, Category::cDekuScrubUpgrades);
if (Scrubsanity.Is(OFF)) {
IncludeAndHide(scrubLocations);
} else {
Unhide(scrubLocations);
}
// Force Include Vanilla Skulltula locations
std::vector<RandomizerCheck> skulltulaLocations =
ctx->GetLocations(ctx->everyPossibleLocation, Category::cSkulltula);
Unhide(skulltulaLocations);
if (Tokensanity.IsNot(TOKENSANITY_ALL_TOKENS)) {
if (Tokensanity.Is(TOKENSANITY_OVERWORLD)) {
// filter overworld skulls so we're just left with dungeons
FilterAndEraseFromPool(skulltulaLocations, [](const RandomizerCheck loc) {
return Rando::StaticData::GetLocation(loc)->GetScene() >= 0x0A;
});
} else if (Tokensanity.Is(TOKENSANITY_DUNGEONS)) {
// filter dungeon skulls so we're just left with overworld
FilterAndEraseFromPool(skulltulaLocations, [](const RandomizerCheck loc) {
return Rando::StaticData::GetLocation(loc)->GetScene() < 0x0A;
});
}
IncludeAndHide(skulltulaLocations);
}
//Force include Cows if Shuffle Cows is Off
std::vector<uint32_t> cowLocations = GetLocations(everyPossibleLocation, Category::cCow);
if (ShuffleCows) {
Unhide(cowLocations);
} else {
IncludeAndHide(cowLocations);
}
// Force Include scrubs if Scrubsanity is Off
std::vector<RandomizerCheck> scrubLocations =
ctx->GetLocations(ctx->everyPossibleLocation, Category::cDekuScrub, Category::cDekuScrubUpgrades);
if (Scrubsanity.Is(OFF)) {
IncludeAndHide(scrubLocations);
} else {
Unhide(scrubLocations);
}
//Force include the Kokiri Sword Chest if Shuffle Kokiri Sword is Off
if (ShuffleKokiriSword) {
Unhide({KF_KOKIRI_SWORD_CHEST});
} else {
IncludeAndHide({KF_KOKIRI_SWORD_CHEST});
}
// Force include Cows if Shuffle Cows is Off
std::vector<RandomizerCheck> cowLocations = ctx->GetLocations(ctx->everyPossibleLocation, Category::cCow);
if (ShuffleCows) {
Unhide(cowLocations);
} else {
IncludeAndHide(cowLocations);
}
//Force include the ocarina locations if Shuffle Ocarinas is Off
std::vector<uint32_t> ocarinaLocations = {LW_GIFT_FROM_SARIA, HF_OCARINA_OF_TIME_ITEM};
if (ShuffleOcarinas) {
Unhide(ocarinaLocations);
} else {
IncludeAndHide(ocarinaLocations);
}
// Force include the Kokiri Sword Chest if Shuffle Kokiri Sword is Off
if (ShuffleKokiriSword) {
Unhide({ RC_KF_KOKIRI_SWORD_CHEST });
} else {
IncludeAndHide({ RC_KF_KOKIRI_SWORD_CHEST });
}
//Force include Malon if Shuffle Weird Egg is Off
if (ShuffleWeirdEgg) {
Unhide({HC_MALON_EGG});
} else {
IncludeAndHide({HC_MALON_EGG});
}
// Force include the ocarina locations if Shuffle Ocarinas is Off
std::vector<RandomizerCheck> ocarinaLocations = { RC_LW_GIFT_FROM_SARIA, RC_HF_OCARINA_OF_TIME_ITEM };
if (ShuffleOcarinas) {
Unhide(ocarinaLocations);
} else {
IncludeAndHide(ocarinaLocations);
}
//Force include Gerudo Membership Card Location if it's not shuffled
if (ShuffleGerudoToken) {
Unhide({GF_GERUDO_MEMBERSHIP_CARD});
} else {
IncludeAndHide({GF_GERUDO_MEMBERSHIP_CARD});
}
// Force include Malon if Shuffle Weird Egg is Off
if (ShuffleWeirdEgg) {
Unhide({ RC_HC_MALON_EGG });
} else {
IncludeAndHide({ RC_HC_MALON_EGG });
}
//Force include Magic Bean salesman if Shuffle Magic Beans is off
if (ShuffleMagicBeans) {
Unhide({ZR_MAGIC_BEAN_SALESMAN});
} else {
IncludeAndHide({ZR_MAGIC_BEAN_SALESMAN});
}
// Force include Gerudo Membership Card GetLocation if it's not shuffled
if (ShuffleGerudoToken) {
Unhide({ RC_GF_GERUDO_MEMBERSHIP_CARD });
} else {
IncludeAndHide({ RC_GF_GERUDO_MEMBERSHIP_CARD });
}
//Force include Medigoron, Granny and Carpet salesman if Shuffle Merchants is off
if (ShuffleMerchants.IsNot(SHUFFLEMERCHANTS_OFF)) {
Unhide({GC_MEDIGORON});
Unhide({KAK_GRANNYS_SHOP});
Unhide({WASTELAND_BOMBCHU_SALESMAN});
} else {
IncludeAndHide({GC_MEDIGORON});
IncludeAndHide({KAK_GRANNYS_SHOP});
IncludeAndHide({WASTELAND_BOMBCHU_SALESMAN});
}
// Force include Magic Bean salesman if Shuffle Magic Beans is off
if (ShuffleMagicBeans) {
Unhide({ RC_ZR_MAGIC_BEAN_SALESMAN });
} else {
IncludeAndHide({ RC_ZR_MAGIC_BEAN_SALESMAN });
}
//Force include frog song rupees if they're not shuffled
if (ShuffleFrogSongRupees) {
Unhide({ZR_FROGS_ZELDAS_LULLABY});
Unhide({ZR_FROGS_EPONAS_SONG});
Unhide({ZR_FROGS_SARIAS_SONG});
Unhide({ZR_FROGS_SUNS_SONG});
Unhide({ZR_FROGS_SONG_OF_TIME});
} else {
IncludeAndHide({ZR_FROGS_ZELDAS_LULLABY});
IncludeAndHide({ZR_FROGS_EPONAS_SONG});
IncludeAndHide({ZR_FROGS_SARIAS_SONG});
IncludeAndHide({ZR_FROGS_SUNS_SONG});
IncludeAndHide({ZR_FROGS_SONG_OF_TIME});
}
// Force include Medigoron, Granny and Carpet salesman if Shuffle Merchants is off
if (ShuffleMerchants.IsNot(SHUFFLEMERCHANTS_OFF)) {
Unhide({ RC_GC_MEDIGORON });
Unhide({ RC_KAK_GRANNYS_SHOP });
Unhide({ RC_WASTELAND_BOMBCHU_SALESMAN });
} else {
IncludeAndHide({ RC_GC_MEDIGORON });
IncludeAndHide({ RC_KAK_GRANNYS_SHOP });
IncludeAndHide({ RC_WASTELAND_BOMBCHU_SALESMAN });
}
//Force include adult trade quest if Shuffle Adult Trade Quest is off
std::vector<uint32_t> adultTradeLocations = {KAK_TRADE_POCKET_CUCCO, LW_TRADE_COJIRO, KAK_TRADE_ODD_MUSHROOM, LW_TRADE_ODD_POTION, GV_TRADE_SAW, DMT_TRADE_BROKEN_SWORD, ZD_TRADE_PRESCRIPTION, LH_TRADE_FROG, DMT_TRADE_EYEDROPS};
if (ShuffleAdultTradeQuest) {
Unhide(adultTradeLocations);
} else {
IncludeAndHide(adultTradeLocations);
}
// Force include frog song rupees if they're not shuffled
if (ShuffleFrogSongRupees) {
Unhide({ RC_ZR_FROGS_ZELDAS_LULLABY });
Unhide({ RC_ZR_FROGS_EPONAS_SONG });
Unhide({ RC_ZR_FROGS_SARIAS_SONG });
Unhide({ RC_ZR_FROGS_SUNS_SONG });
Unhide({ RC_ZR_FROGS_SONG_OF_TIME });
} else {
IncludeAndHide({ RC_ZR_FROGS_ZELDAS_LULLABY });
IncludeAndHide({ RC_ZR_FROGS_EPONAS_SONG });
IncludeAndHide({ RC_ZR_FROGS_SARIAS_SONG });
IncludeAndHide({ RC_ZR_FROGS_SUNS_SONG });
IncludeAndHide({ RC_ZR_FROGS_SONG_OF_TIME });
}
//Force include Chest Game keys if Shuffle Chest Minigame is off
std::vector<uint32_t> ChestMinigameLocations = {
MARKET_TREASURE_CHEST_GAME_ITEM_1, MARKET_TREASURE_CHEST_GAME_ITEM_2, MARKET_TREASURE_CHEST_GAME_ITEM_3,
MARKET_TREASURE_CHEST_GAME_ITEM_4, MARKET_TREASURE_CHEST_GAME_ITEM_5
};
if (ShuffleChestMinigame) {
Unhide(ChestMinigameLocations);
} else {
IncludeAndHide(ChestMinigameLocations);
}
// Force include adult trade quest if Shuffle Adult Trade Quest is off
std::vector<RandomizerCheck> adultTradeLocations = { RC_KAK_TRADE_POCKET_CUCCO, RC_LW_TRADE_COJIRO,
RC_KAK_TRADE_ODD_MUSHROOM, RC_LW_TRADE_ODD_POTION,
RC_GV_TRADE_SAW, RC_DMT_TRADE_BROKEN_SWORD,
RC_ZD_TRADE_PRESCRIPTION, RC_LH_TRADE_FROG,
RC_DMT_TRADE_EYEDROPS };
if (ShuffleAdultTradeQuest) {
Unhide(adultTradeLocations);
} else {
IncludeAndHide(adultTradeLocations);
}
//Force include 100 GS reward if it isn't shuffled
if (Shuffle100GSReward) {
Unhide({KAK_100_GOLD_SKULLTULA_REWARD});
} else {
IncludeAndHide({KAK_100_GOLD_SKULLTULA_REWARD});
}
// Force include Chest Game keys if Shuffle Chest Minigame is off
std::vector<RandomizerCheck> ChestMinigameLocations = { RC_MARKET_TREASURE_CHEST_GAME_ITEM_1,
RC_MARKET_TREASURE_CHEST_GAME_ITEM_2,
RC_MARKET_TREASURE_CHEST_GAME_ITEM_3,
RC_MARKET_TREASURE_CHEST_GAME_ITEM_4,
RC_MARKET_TREASURE_CHEST_GAME_ITEM_5 };
if (ShuffleChestMinigame) {
Unhide(ChestMinigameLocations);
} else {
IncludeAndHide(ChestMinigameLocations);
}
//Force include Triforce Hunt if it's off
if (TriforceHunt) {
Unhide({ TRIFORCE_COMPLETED });
} else {
IncludeAndHide({ TRIFORCE_COMPLETED });
}
// Force include 100 GS reward if it isn't shuffled
if (Shuffle100GSReward) {
Unhide({ RC_KAK_100_GOLD_SKULLTULA_REWARD });
} else {
IncludeAndHide({ RC_KAK_100_GOLD_SKULLTULA_REWARD });
}
//Force include Map and Compass Chests when Vanilla
std::vector<uint32_t> mapChests = GetLocations(everyPossibleLocation, Category::cVanillaMap);
std::vector<uint32_t> compassChests = GetLocations(everyPossibleLocation, Category::cVanillaCompass);
if (MapsAndCompasses.Is(MAPSANDCOMPASSES_VANILLA)) {
IncludeAndHide(mapChests);
IncludeAndHide(compassChests);
} else {
Unhide(mapChests);
Unhide(compassChests);
}
// Force include Triforce Hunt if it's off
if (TriforceHunt) {
Unhide({ RC_TRIFORCE_COMPLETED });
} else {
IncludeAndHide({ RC_TRIFORCE_COMPLETED });
}
//Force include Vanilla Small Key Locations (except gerudo Fortress) on Vanilla Keys
std::vector<uint32_t> smallKeyChests = GetLocations(everyPossibleLocation, Category::cVanillaSmallKey);
if (Keysanity.Is(KEYSANITY_VANILLA)) {
IncludeAndHide(smallKeyChests);
} else {
Unhide(smallKeyChests);
}
// Force include Map and Compass Chests when Vanilla
std::vector<RandomizerCheck> mapChests = ctx->GetLocations(ctx->everyPossibleLocation, Category::cVanillaMap);
std::vector<RandomizerCheck> compassChests =
ctx->GetLocations(ctx->everyPossibleLocation, Category::cVanillaCompass);
if (MapsAndCompasses.Is(MAPSANDCOMPASSES_VANILLA)) {
IncludeAndHide(mapChests);
IncludeAndHide(compassChests);
} else {
Unhide(mapChests);
Unhide(compassChests);
}
//Force include Gerudo Fortress carpenter fights if GF Small Keys are Vanilla
std::vector<uint32_t> vanillaGFKeyLocations = GetLocations(everyPossibleLocation, Category::cVanillaGFSmallKey);
if (GerudoKeys.Is(GERUDOKEYS_VANILLA)) {
IncludeAndHide(vanillaGFKeyLocations);
} else {
Unhide(vanillaGFKeyLocations);
}
// Force include Vanilla Small Key Locations (except gerudo Fortress) on Vanilla Keys
std::vector<RandomizerCheck> smallKeyChests =
ctx->GetLocations(ctx->everyPossibleLocation, Category::cVanillaSmallKey);
if (Keysanity.Is(KEYSANITY_VANILLA)) {
IncludeAndHide(smallKeyChests);
} else {
Unhide(smallKeyChests);
}
//Force include Boss Key Chests if Boss Keys are Vanilla
std::vector<uint32_t> bossKeyChests = GetLocations(everyPossibleLocation, Category::cVanillaBossKey);
if (BossKeysanity.Is(BOSSKEYSANITY_VANILLA)) {
IncludeAndHide(bossKeyChests);
} else {
Unhide(bossKeyChests);
}
// Force include Gerudo Fortress carpenter fights if GF Small Keys are Vanilla
std::vector<RandomizerCheck> vanillaGFKeyLocations =
ctx->GetLocations(ctx->everyPossibleLocation, Category::cVanillaGFSmallKey);
if (GerudoKeys.Is(GERUDOKEYS_VANILLA)) {
IncludeAndHide(vanillaGFKeyLocations);
} else {
Unhide(vanillaGFKeyLocations);
}
//Force include Ganons Boss Key Chest if ganons boss key has to be there
if (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA)) {
IncludeAndHide({GANONS_TOWER_BOSS_KEY_CHEST});
} else {
Unhide({GANONS_TOWER_BOSS_KEY_CHEST});
}
// Force include Boss Key Chests if Boss Keys are Vanilla
std::vector<RandomizerCheck> bossKeyChests =
ctx->GetLocations(ctx->everyPossibleLocation, Category::cVanillaBossKey);
if (BossKeysanity.Is(BOSSKEYSANITY_VANILLA)) {
IncludeAndHide(bossKeyChests);
} else {
Unhide(bossKeyChests);
}
//Force include Light Arrow item if ganons boss key has to be there
if (GanonsBossKey.Value<uint8_t>() >= GANONSBOSSKEY_LACS_VANILLA) {
IncludeAndHide({TOT_LIGHT_ARROWS_CUTSCENE});
} else {
Unhide({TOT_LIGHT_ARROWS_CUTSCENE});
}
// Force include Ganons Boss Key Chest if ganons boss key has to be there
if (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA)) {
IncludeAndHide({ RC_GANONS_TOWER_BOSS_KEY_CHEST });
} else {
Unhide({ RC_GANONS_TOWER_BOSS_KEY_CHEST });
}
// Force include Light Arrow item if ganons boss key has to be there
if (GanonsBossKey.Value<uint8_t>() >= GANONSBOSSKEY_LACS_VANILLA) {
IncludeAndHide({ RC_TOT_LIGHT_ARROWS_CUTSCENE });
} else {
Unhide({ RC_TOT_LIGHT_ARROWS_CUTSCENE });
}
}
uint8_t DungeonsOfType(uint8_t type) {
@@ -2207,10 +2225,10 @@ namespace Settings {
}
LocationsReachable.SetSelectedIndex(cvarSettings[RSK_ALL_LOCATIONS_REACHABLE]);
AddExcludedOptions();
for (auto locationKey : everyPossibleLocation) {
auto location = Location(locationKey);
auto ctx = Rando::Context::GetInstance();
ctx->AddExcludedOptions();
for (auto locationKey : ctx->everyPossibleLocation) {
auto location = ctx->GetItemLocation(locationKey);
if (excludedLocations.count(location->GetRandomizerCheck())) {
location->GetExcludedOption()->SetSelectedIndex(1);
} else {

View File

@@ -744,7 +744,7 @@ class Menu {
namespace Settings {
void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations, std::set<RandomizerTrick> enabledTricks);
SettingsContext FillContext();
void ResolveExcludedLocationConflicts();
//void ResolveExcludedLocationConflicts();
void RandomizeAllSettings(const bool selectOptions = false);
void ForceChange(uint32_t kDown, Option* currentSetting);
const std::vector<Menu*> GetAllOptionMenus();

View File

@@ -1,8 +1,6 @@
#include "item_location.hpp"
#include "item_pool.hpp"
#include "location_access.hpp"
#include "random.hpp"
#include "item.hpp"
#include "shops.hpp"
#include <math.h>
@@ -18,10 +16,11 @@ bool initTrickNames = false; //Indicates if trick ice trap names have been initi
//Set vanilla shop item locations before potentially shuffling
void PlaceVanillaShopItems() {
auto ctx = Rando::Context::GetInstance();
//Loop to place vanilla items in each location
for (size_t i = 0; i < ShopLocationLists.size(); i++) {
for (size_t j = 0; j < ShopLocationLists[i].size(); j++) {
Location(ShopLocationLists[i][j])->PlaceVanillaItem();
for (size_t i = 0; i < Rando::StaticData::shopLocationLists.size(); i++) {
for (size_t j = 0; j < Rando::StaticData::shopLocationLists[i].size(); j++) {
ctx->GetItemLocation(Rando::StaticData::shopLocationLists[i][j])->PlaceVanillaItem();
}
}
}
@@ -31,77 +30,77 @@ void PlaceVanillaShopItems() {
//The first 32 items here will always be present in shops
//Shopsanity 4 will only have the first 32, shopsanity 1 will have the first 56, etc.
//Shopsanity random will have anywhere from the first 32 to the first 56, so the order of items after 32 is relevant
std::vector<uint32_t> GetMinVanillaShopItems(int total_replaced) {
std::vector<uint32_t> minShopItems = {
BUY_DEKU_SHIELD,
BUY_HYLIAN_SHIELD,
BUY_GORON_TUNIC,
BUY_ZORA_TUNIC,
BUY_DEKU_NUT_5,
BUY_DEKU_NUT_5,
BUY_DEKU_NUT_10,
BUY_DEKU_STICK_1,
BUY_DEKU_STICK_1,
BUY_DEKU_SEEDS_30,
BUY_ARROWS_10,
BUY_ARROWS_10,
BUY_ARROWS_30,
BUY_ARROWS_50,
BUY_BOMBCHU_10,
BUY_BOMBCHU_10,
BUY_BOMBCHU_10,
BUY_BOMBCHU_20,
BUY_BOMBS_525,
BUY_BOMBS_535,
BUY_BOMBS_10,
BUY_BOMBS_20,
BUY_GREEN_POTION,
BUY_RED_POTION_30,
BUY_BLUE_FIRE,
BUY_FAIRYS_SPIRIT,
BUY_BOTTLE_BUG,
BUY_FISH,
std::vector<RandomizerGet> GetMinVanillaShopItems(int total_replaced) {
std::vector<RandomizerGet> minShopItems = {
RG_BUY_DEKU_SHIELD,
RG_BUY_HYLIAN_SHIELD,
RG_BUY_GORON_TUNIC,
RG_BUY_ZORA_TUNIC,
RG_BUY_DEKU_NUT_5,
RG_BUY_DEKU_NUT_5,
RG_BUY_DEKU_NUT_10,
RG_BUY_DEKU_STICK_1,
RG_BUY_DEKU_STICK_1,
RG_BUY_DEKU_SEEDS_30,
RG_BUY_ARROWS_10,
RG_BUY_ARROWS_10,
RG_BUY_ARROWS_30,
RG_BUY_ARROWS_50,
RG_BUY_BOMBCHU_10,
RG_BUY_BOMBCHU_10,
RG_BUY_BOMBCHU_10,
RG_BUY_BOMBCHU_20,
RG_BUY_BOMBS_525,
RG_BUY_BOMBS_535,
RG_BUY_BOMBS_10,
RG_BUY_BOMBS_20,
RG_BUY_GREEN_POTION,
RG_BUY_RED_POTION_30,
RG_BUY_BLUE_FIRE,
RG_BUY_FAIRYS_SPIRIT,
RG_BUY_BOTTLE_BUG,
RG_BUY_FISH,
//^First 28 items from OoTR
BUY_HYLIAN_SHIELD,
BUY_BOTTLE_BUG,
BUY_DEKU_STICK_1,
BUY_FAIRYS_SPIRIT,
RG_BUY_HYLIAN_SHIELD,
RG_BUY_BOTTLE_BUG,
RG_BUY_DEKU_STICK_1,
RG_BUY_FAIRYS_SPIRIT,
//^First 32 items: Always guaranteed
BUY_BLUE_FIRE,
BUY_FISH,
BUY_BOMBCHU_10,
BUY_DEKU_NUT_5,
BUY_ARROWS_10,
BUY_BOMBCHU_20,
BUY_BOMBS_535,
BUY_RED_POTION_30,
RG_BUY_BLUE_FIRE,
RG_BUY_FISH,
RG_BUY_BOMBCHU_10,
RG_BUY_DEKU_NUT_5,
RG_BUY_ARROWS_10,
RG_BUY_BOMBCHU_20,
RG_BUY_BOMBS_535,
RG_BUY_RED_POTION_30,
//^First 40 items: Exist on shopsanity 3 or less
BUY_BOMBS_30,
BUY_BOMBCHU_20,
BUY_DEKU_NUT_5,
BUY_ARROWS_10,
BUY_DEKU_NUT_5,
BUY_ARROWS_30,
BUY_RED_POTION_40,
BUY_FISH,
RG_BUY_BOMBS_30,
RG_BUY_BOMBCHU_20,
RG_BUY_DEKU_NUT_5,
RG_BUY_ARROWS_10,
RG_BUY_DEKU_NUT_5,
RG_BUY_ARROWS_30,
RG_BUY_RED_POTION_40,
RG_BUY_FISH,
//^First 48 items: Exist on shopsanity 2 or less
BUY_BOMBCHU_20,
BUY_ARROWS_30,
BUY_RED_POTION_50,
BUY_ARROWS_30,
BUY_DEKU_NUT_5,
BUY_ARROWS_50,
BUY_ARROWS_50,
BUY_GREEN_POTION,
RG_BUY_BOMBCHU_20,
RG_BUY_ARROWS_30,
RG_BUY_RED_POTION_50,
RG_BUY_ARROWS_30,
RG_BUY_DEKU_NUT_5,
RG_BUY_ARROWS_50,
RG_BUY_ARROWS_50,
RG_BUY_GREEN_POTION,
//^First 56 items: Exist on shopsanity 1 or less
BUY_POE,
BUY_POE,
BUY_HEART,
BUY_HEART,
BUY_HEART,
BUY_HEART,
BUY_HEART,
BUY_HEART,
RG_BUY_POE,
RG_BUY_POE,
RG_BUY_HEART,
RG_BUY_HEART,
RG_BUY_HEART,
RG_BUY_HEART,
RG_BUY_HEART,
RG_BUY_HEART,
//^All 64 items: Only exist with shopsanity 0
};
//Now delete however many items there are to replace
@@ -901,9 +900,9 @@ Text GetIceTrapName(uint8_t id) {
//Get shop index based on a given location
static std::map<std::string_view, int> ShopNameToNum = {{"KF Shop", 0}, {"Kak Potion Shop", 1}, {"MK Bombchu Shop", 2}, {"MK Potion Shop", 3},
{"MK Bazaar", 4}, {"Kak Bazaar", 5}, {"ZD Shop", 6}, {"GC Shop", 7}};
int GetShopIndex(uint32_t loc) {
int GetShopIndex(RandomizerCheck loc) {
//Kind of hacky, but extract the shop and item position from the name
const std::string& name(Location(loc)->GetName());
const std::string& name(Rando::StaticData::GetLocation(loc)->GetName());
int split = name.find(" Item ");
std::string_view shop(name.c_str(), split);
int pos = std::stoi(name.substr(split+6, 1)) - 1;

View File

@@ -1,6 +1,5 @@
#pragma once
#include "item.hpp"
#include "item_location.hpp"
#include "../context.h"
#include <vector>
#include <array>
@@ -12,12 +11,12 @@ struct ItemAndPrice {
};
extern void PlaceVanillaShopItems();
extern std::vector<uint32_t> GetMinVanillaShopItems(int total_replaced);
extern std::vector<RandomizerGet> GetMinVanillaShopItems(int total_replaced);
extern int GetRandomShopPrice();
extern int16_t GetRandomScrubPrice();
extern int GetShopsanityReplaceAmount();
extern Text GetIceTrapName(uint8_t id);
extern int GetShopIndex(uint32_t loc);
extern int GetShopIndex(RandomizerCheck loc);
extern int TransformShopIndex(int index);
extern std::vector<ItemAndPrice> NonShopItems;

View File

@@ -1,8 +1,8 @@
#include "spoiler_log.hpp"
#include "dungeon.hpp"
#include "item_list.hpp"
#include "item_location.hpp"
#include "../static_data.h"
#include "../context.h"
#include "entrance.hpp"
#include "random.hpp"
#include "settings.hpp"
@@ -30,12 +30,12 @@
#include <filesystem>
#include <variables.h>
#include <libultraship/libultraship.h>
#include <Context.h>
using json = nlohmann::ordered_json;
json jsonData;
std::map<HintKey, ItemLocation*> hintedLocations;
std::map<RandomizerHintTextKey, Rando::ItemLocation*> hintedLocations;
extern std::unordered_map<HintType, std::string> hintTypeNames;
extern std::array<std::string, 17> hintCategoryNames;
@@ -79,6 +79,7 @@ static auto GetPlacementLogPath() {
}
void WriteIngameSpoilerLog() {
auto ctx = Rando::Context::GetInstance();
uint16_t spoilerItemIndex = 0;
uint32_t spoilerStringOffset = 0;
uint16_t spoilerSphereItemoffset = 0;
@@ -91,28 +92,29 @@ void WriteIngameSpoilerLog() {
// Some item names, like gold skulltula tokens, can appear many times in a playthrough
std::unordered_map<uint32_t, uint16_t>
itemLocationsMap; // Map of LocationKey to an index into spoiler data item locations
itemLocationsMap.reserve(allLocations.size());
itemLocationsMap.reserve(ctx->allLocations.size());
std::unordered_map<std::string, uint16_t>
stringOffsetMap; // Map of strings to their offset into spoiler string data array
stringOffsetMap.reserve(allLocations.size() * 2);
stringOffsetMap.reserve(ctx->allLocations.size() * 2);
// Sort all locations by their group, so the in-game log can show a group of items by simply starting/ending at
// certain indices
std::stable_sort(allLocations.begin(), allLocations.end(), [](const uint32_t& a, const uint32_t& b) {
auto groupA = Location(a)->GetCollectionCheckGroup();
auto groupB = Location(b)->GetCollectionCheckGroup();
std::stable_sort(ctx->allLocations.begin(), ctx->allLocations.end(), [](const RandomizerCheck& a, const RandomizerCheck& b) {
auto groupA = Rando::StaticData::GetLocation(a)->GetCollectionCheckGroup();
auto groupB = Rando::StaticData::GetLocation(b)->GetCollectionCheckGroup();
return groupA < groupB;
});
for (const uint32_t key : allLocations) {
auto loc = Location(key);
for (const RandomizerCheck key : ctx->allLocations) {
auto loc = Rando::StaticData::GetLocation(key);
auto itemLocation = ctx->GetItemLocation(key);
// Hide excluded locations from ingame tracker
if (loc->IsExcluded()) {
continue;
}
// if (loc->IsExcluded()) {
// continue;
// }
// Cows
else if (!Settings::ShuffleCows && loc->IsCategory(Category::cCow)) {
if (!Settings::ShuffleCows && loc->IsCategory(Category::cCow)) {
continue;
}
// Merchants
@@ -130,9 +132,9 @@ void WriteIngameSpoilerLog() {
}
// Gerudo Fortress
else if ((Settings::GerudoFortress.Is(GERUDOFORTRESS_OPEN) &&
(loc->IsCategory(Category::cVanillaGFSmallKey) || loc->GetHintKey() == GF_GERUDO_MEMBERSHIP_CARD)) ||
(loc->IsCategory(Category::cVanillaGFSmallKey) || loc->GetHintKey() == RHT_GF_GERUDO_MEMBERSHIP_CARD)) ||
(Settings::GerudoFortress.Is(GERUDOFORTRESS_FAST) && loc->IsCategory(Category::cVanillaGFSmallKey) &&
loc->GetHintKey() != GF_NORTH_F1_CARPENTER)) {
loc->GetHintKey() != RHT_GF_NORTH_F1_CARPENTER)) {
continue;
}
@@ -151,8 +153,8 @@ void WriteIngameSpoilerLog() {
}
}
// PURPLE TODO: LOCALIZATION
auto locItem = loc->GetPlacedItemName().GetEnglish();
if (loc->GetPlacedItemKey() == ICE_TRAP && loc->IsCategory(Category::cShop)) {
auto locItem = itemLocation->GetPlacedItemName().GetEnglish();
if (itemLocation->GetPlacedRandomizerGet() == RG_ICE_TRAP && loc->IsCategory(Category::cShop)) {
locItem = NonShopItems[TransformShopIndex(GetShopIndex(key))].Name.GetEnglish();
}
if (stringOffsetMap.find(locItem) == stringOffsetMap.end()) {
@@ -175,10 +177,10 @@ void WriteIngameSpoilerLog() {
spoilerData.ItemLocations[spoilerItemIndex].LocationFlag = loc->GetCollectionCheck().flag;
// Collect Type and Reveal Type
if (key == GANON) {
if (key == RC_GANON) {
spoilerData.ItemLocations[spoilerItemIndex].CollectType = COLLECTTYPE_NEVER;
spoilerData.ItemLocations[spoilerItemIndex].RevealType = REVEALTYPE_ALWAYS;
} else if (key == MARKET_BOMBCHU_BOWLING_BOMBCHUS) {
} else if (key == RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS) {
spoilerData.ItemLocations[spoilerItemIndex].CollectType = COLLECTTYPE_REPEATABLE;
spoilerData.ItemLocations[spoilerItemIndex].RevealType = REVEALTYPE_ALWAYS;
}
@@ -189,9 +191,9 @@ void WriteIngameSpoilerLog() {
} else {
spoilerData.ItemLocations[spoilerItemIndex].RevealType = REVEALTYPE_SCENE;
}
if (loc->GetPlacedItem().GetItemType() == ITEMTYPE_REFILL ||
loc->GetPlacedItem().GetItemType() == ITEMTYPE_SHOP ||
loc->GetPlacedItem().GetHintKey() == PROGRESSIVE_BOMBCHUS) {
if (itemLocation->GetPlacedItem().GetItemType() == ITEMTYPE_REFILL ||
itemLocation->GetPlacedItem().GetItemType() == ITEMTYPE_SHOP ||
itemLocation->GetPlacedItem().GetHintKey() == RHT_PROGRESSIVE_BOMBCHUS) {
spoilerData.ItemLocations[spoilerItemIndex].CollectType = COLLECTTYPE_REPEATABLE;
}
}
@@ -228,19 +230,19 @@ void WriteIngameSpoilerLog() {
bool playthroughItemNotFound = false;
// Write playthrough data to in-game spoiler log
if (!spoilerOutOfSpace) {
for (uint32_t i = 0; i < playthroughLocations.size(); i++) {
for (uint32_t i = 0; i < ctx->playthroughLocations.size(); i++) {
if (i >= SPOILER_SPHERES_MAX) {
spoilerOutOfSpace = true;
break;
}
spoilerData.Spheres[i].ItemLocationsOffset = spoilerSphereItemoffset;
for (uint32_t loc = 0; loc < playthroughLocations[i].size(); ++loc) {
for (uint32_t loc = 0; loc < ctx->playthroughLocations[i].size(); ++loc) {
if (spoilerSphereItemoffset >= SPOILER_ITEMS_MAX) {
spoilerOutOfSpace = true;
break;
}
const auto foundItemLoc = itemLocationsMap.find(playthroughLocations[i][loc]);
const auto foundItemLoc = itemLocationsMap.find(ctx->playthroughLocations[i][loc]);
if (foundItemLoc != itemLocationsMap.end()) {
spoilerData.SphereItemLocations[spoilerSphereItemoffset++] = foundItemLoc->second;
} else {
@@ -252,24 +254,25 @@ void WriteIngameSpoilerLog() {
}
}
if (spoilerOutOfSpace || playthroughItemNotFound) {
printf("%sError!%s ", YELLOW, WHITE);
printf("Error! ");
}
}
}
// Writes the location to the specified node.
static void WriteLocation(
std::string sphere, const uint32_t locationKey, const bool withPadding = false) {
ItemLocation* location = Location(locationKey);
std::string sphere, const RandomizerCheck locationKey, const bool withPadding = false) {
Rando::Location* location = Rando::StaticData::GetLocation(locationKey);
Rando::ItemLocation* itemLocation = Rando::Context::GetInstance()->GetItemLocation(locationKey);
// auto node = parentNode->InsertNewChildElement("location");
switch (gSaveContext.language) {
case LANGUAGE_ENG:
default:
jsonData["playthrough"][sphere][location->GetName()] = location->GetPlacedItemName().GetEnglish();
jsonData["playthrough"][sphere][location->GetName()] = itemLocation->GetPlacedItemName().GetEnglish();
break;
case LANGUAGE_FRA:
jsonData["playthrough"][sphere][location->GetName()] = location->GetPlacedItemName().GetFrench();
jsonData["playthrough"][sphere][location->GetName()] = itemLocation->GetPlacedItemName().GetFrench();
break;
}
// node->SetAttribute("name", location->GetName().c_str());
@@ -412,7 +415,7 @@ static void WriteSettings(const bool printAll = false) {
// spoilerLog.RootElement()->InsertEndChild(parentNode);
// for (const uint32_t key : allLocations) {
// ItemLocation* location = Location(key);
// ItemLocation* location = GetLocation(key);
// settingsJsonData["locations"][location->GetName()] = location->GetPlacedItemName().english;
// }
}
@@ -570,13 +573,14 @@ static void WriteRequiredTrials() {
// Writes the intended playthrough to the spoiler log, separated into spheres.
static void WritePlaythrough() {
// auto playthroughNode = spoilerLog.NewElement("playthrough");
auto ctx = Rando::Context::GetInstance();
for (uint32_t i = 0; i < playthroughLocations.size(); ++i) {
for (uint32_t i = 0; i < ctx->playthroughLocations.size(); ++i) {
auto sphereNum = std::to_string(i);
std::string sphereString = "sphere ";
if (i < 10) sphereString += "0";
sphereString += sphereNum;
for (const uint32_t key : playthroughLocations[i]) {
for (const RandomizerCheck key : ctx->playthroughLocations[i]) {
WriteLocation(sphereString, key, true);
}
}
@@ -601,7 +605,7 @@ static void WriteShuffledEntrances() {
static void WriteWayOfTheHeroLocation(tinyxml2::XMLDocument& spoilerLog) {
auto parentNode = spoilerLog.NewElement("way-of-the-hero-locations");
for (const uint32_t key : wothLocations) {
for (const RandomizerCheck key : Rando::Context::GetInstance()->wothLocations) {
// WriteLocation(parentNode, key, true);
}
@@ -660,8 +664,11 @@ std::string AutoFormatHintTextString(std::string unformattedHintTextString) {
return textStr;
}
ItemLocation* GetItemLocation(uint32_t item) {
return Location(FilterFromPool(allLocations, [item](const uint32_t loc){return Location(loc)->GetPlaceduint32_t() == item;})[0]);
Rando::ItemLocation* GetItemLocation(RandomizerGet item) {
auto ctx = Rando::Context::GetInstance();
return ctx->GetItemLocation(FilterFromPool(ctx->allLocations, [item, ctx](const RandomizerCheck loc) {
return ctx->GetItemLocation(loc)->GetPlacedRandomizerGet() == item;
})[0]);
}
// Writes the hints to the spoiler log, if they are enabled.
@@ -709,30 +716,37 @@ static void WriteHints(int language) {
break;
}
ItemLocation* emeraldLoc = GetItemLocation(KOKIRI_EMERALD);
ItemLocation* rubyLoc = GetItemLocation(GORON_RUBY);
ItemLocation* sapphireLoc = GetItemLocation(ZORA_SAPPHIRE);
Rando::ItemLocation* emeraldLoc = GetItemLocation(RG_KOKIRI_EMERALD);
Rando::ItemLocation* rubyLoc = GetItemLocation(RG_GORON_RUBY);
Rando::ItemLocation* sapphireLoc = GetItemLocation(RG_ZORA_SAPPHIRE);
std::string emeraldArea;
std::string erubyArea;
std::string sapphireArea;
jsonData["childAltar"]["rewards"]["emeraldLoc"] = emeraldLoc->GetName();
jsonData["childAltar"]["rewards"]["rubyLoc"] = rubyLoc->GetName();
jsonData["childAltar"]["rewards"]["sapphireLoc"] = sapphireLoc->GetName();
jsonData["childAltar"]["rewards"]["emeraldLoc"] = Rando::StaticData::GetLocation(emeraldLoc->GetRandomizerCheck())->GetName();
jsonData["childAltar"]["rewards"]["rubyLoc"] = Rando::StaticData::GetLocation(rubyLoc->GetRandomizerCheck())->GetName();
jsonData["childAltar"]["rewards"]["sapphireLoc"] =
Rando::StaticData::GetLocation(sapphireLoc->GetRandomizerCheck())->GetName();
ItemLocation* forestMedallionLoc = GetItemLocation(FOREST_MEDALLION);
ItemLocation* fireMedallionLoc = GetItemLocation(FIRE_MEDALLION);
ItemLocation* waterMedallionLoc = GetItemLocation(WATER_MEDALLION);
ItemLocation* shadowMedallionLoc = GetItemLocation(SHADOW_MEDALLION);
ItemLocation* spiritMedallionLoc = GetItemLocation(SPIRIT_MEDALLION);
ItemLocation* lightMedallionLoc = GetItemLocation(LIGHT_MEDALLION);
Rando::ItemLocation* forestMedallionLoc = GetItemLocation(RG_FOREST_MEDALLION);
Rando::ItemLocation* fireMedallionLoc = GetItemLocation(RG_FIRE_MEDALLION);
Rando::ItemLocation* waterMedallionLoc = GetItemLocation(RG_WATER_MEDALLION);
Rando::ItemLocation* shadowMedallionLoc = GetItemLocation(RG_SHADOW_MEDALLION);
Rando::ItemLocation* spiritMedallionLoc = GetItemLocation(RG_SPIRIT_MEDALLION);
Rando::ItemLocation* lightMedallionLoc = GetItemLocation(RG_LIGHT_MEDALLION);
jsonData["adultAltar"]["rewards"]["forestMedallionLoc"] = forestMedallionLoc->GetName();
jsonData["adultAltar"]["rewards"]["fireMedallionLoc"] = fireMedallionLoc->GetName();
jsonData["adultAltar"]["rewards"]["waterMedallionLoc"] = waterMedallionLoc->GetName();
jsonData["adultAltar"]["rewards"]["shadowMedallionLoc"] = shadowMedallionLoc->GetName();
jsonData["adultAltar"]["rewards"]["spiritMedallionLoc"] = spiritMedallionLoc->GetName();
jsonData["adultAltar"]["rewards"]["lightMedallionLoc"] = lightMedallionLoc->GetName();
jsonData["adultAltar"]["rewards"]["forestMedallionLoc"] =
Rando::StaticData::GetLocation(forestMedallionLoc->GetRandomizerCheck())->GetName();
jsonData["adultAltar"]["rewards"]["fireMedallionLoc"] =
Rando::StaticData::GetLocation(fireMedallionLoc->GetRandomizerCheck())->GetName();
jsonData["adultAltar"]["rewards"]["waterMedallionLoc"] =
Rando::StaticData::GetLocation(waterMedallionLoc->GetRandomizerCheck())->GetName();
jsonData["adultAltar"]["rewards"]["shadowMedallionLoc"] =
Rando::StaticData::GetLocation(shadowMedallionLoc->GetRandomizerCheck())->GetName();
jsonData["adultAltar"]["rewards"]["spiritMedallionLoc"] =
Rando::StaticData::GetLocation(spiritMedallionLoc->GetRandomizerCheck())->GetName();
jsonData["adultAltar"]["rewards"]["lightMedallionLoc"] =
Rando::StaticData::GetLocation(lightMedallionLoc->GetRandomizerCheck())->GetName();
std::string ganonText = AutoFormatHintTextString(unformattedGanonText);
std::string ganonHintText = AutoFormatHintTextString(unformattedGanonHintText);
@@ -747,7 +761,8 @@ static void WriteHints(int language) {
jsonData["dampeText"] = dampesText;
jsonData["dampeHintLoc"] = GetDampeHintLoc();
jsonData["gregText"] = gregText;
jsonData["gregLoc"] = GetItemLocation(GREG_RUPEE)->GetName();
jsonData["gregLoc"] =
Rando::StaticData::GetLocation(GetItemLocation(RG_GREG_RUPEE)->GetRandomizerCheck())->GetName();
jsonData["sheikText"] = sheikText;
jsonData["sariaText"] = sariaText;
jsonData["sariaHintLoc"] = GetSariaHintLoc();
@@ -755,41 +770,43 @@ static void WriteHints(int language) {
if (Settings::GossipStoneHints.Is(HINTS_NO_HINTS)) {
return;
}
for (const uint32_t key : gossipStoneLocations) {
ItemLocation* location = Location(key);
ItemLocation* hintedLocation = Location(location->GetHintedLocation());
auto ctx = Rando::Context::GetInstance();
for (const RandomizerCheck key : Rando::StaticData::gossipStoneLocations) {
Rando::Hint* hint = ctx->GetHint((RandomizerHintKey)(key - RC_DMC_GOSSIP_STONE + 1));
Rando::ItemLocation* hintedLocation = ctx->GetItemLocation(hint->GetHintedLocation());
std::string unformattedHintTextString;
switch (language) {
case 0:
default:
unformattedHintTextString = location->GetPlacedItemName().GetEnglish();
unformattedHintTextString = hint->GetText().GetEnglish();
break;
case 2:
unformattedHintTextString = location->GetPlacedItemName().GetFrench();
unformattedHintTextString = hint->GetText().GetFrench();
break;
}
HintType hintType = location->GetHintType();
HintType hintType = hint->GetHintType();
std::string textStr = AutoFormatHintTextString(unformattedHintTextString);
jsonData["hints"][location->GetName()]["hint"] = textStr;
jsonData["hints"][location->GetName()]["type"] = hintTypeNames.find(hintType)->second;
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["hint"] = textStr;
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["type"] = hintTypeNames.find(hintType)->second;
if (hintType == HINT_TYPE_ITEM || hintType == HINT_TYPE_NAMED_ITEM || hintType == HINT_TYPE_WOTH) {
jsonData["hints"][location->GetName()]["item"] = hintedLocation->GetPlacedItemName().GetEnglish();
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["item"] = hintedLocation->GetPlacedItemName().GetEnglish();
if (hintType != HINT_TYPE_NAMED_ITEM || hintType == HINT_TYPE_WOTH) {
jsonData["hints"][location->GetName()]["location"] = hintedLocation->GetName();
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["location"] =
Rando::StaticData::GetLocation(hintedLocation->GetRandomizerCheck())->GetName();
}
}
if (hintType != HINT_TYPE_TRIAL && hintType != HINT_TYPE_JUNK) {
jsonData["hints"][location->GetName()]["area"] = location->GetHintedRegion();
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["area"] = hint->GetHintedRegion();
}
}
}
static void WriteAllLocations(int language) {
for (const uint32_t key : allLocations) {
ItemLocation* location = Location(key);
auto ctx = Rando::Context::GetInstance();
for (const RandomizerCheck key : ctx->allLocations) {
Rando::ItemLocation* location = ctx->GetItemLocation(key);
std::string placedItemName;
switch (language) {
@@ -806,52 +823,43 @@ static void WriteAllLocations(int language) {
// just add the name of the item and move on
if (!location->HasScrubsanityPrice() &&
!location->HasShopsanityPrice() &&
location->GetPlacedItemKey() != ICE_TRAP) {
location->GetPlacedRandomizerGet() != RG_ICE_TRAP) {
jsonData["locations"][location->GetName()] = placedItemName;
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()] = placedItemName;
continue;
}
// We're dealing with a complex item, build out the json object for it
jsonData["locations"][location->GetName()]["item"] = placedItemName;
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["item"] = placedItemName;
if (location->HasScrubsanityPrice() || location->HasShopsanityPrice()) {
jsonData["locations"][location->GetName()]["price"] = location->GetPrice();
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["price"] =
location->GetPrice();
}
if (location->IsHintedAt()) {
hintedLocations.emplace(location->GetHintKey(), location);
hintedLocations.emplace(Rando::StaticData::GetLocation(key)->GetHintKey(), location);
}
if (location->GetPlacedItemKey() == ICE_TRAP) {
if (location->GetPlacedRandomizerGet() == RG_ICE_TRAP) {
switch (language) {
case 0:
default:
jsonData["locations"][location->GetName()]["model"] =
ItemFromGIID(iceTrapModels[location->GetRandomizerCheck()]).GetName().english;
jsonData["locations"][location->GetName()]["trickName"] =
GetIceTrapName(iceTrapModels[location->GetRandomizerCheck()]).english;
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["model"] =
Rando::StaticData::ItemFromGIID(ctx->iceTrapModels[location->GetRandomizerCheck()]).GetName().english;
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["trickName"] =
GetIceTrapName(ctx->iceTrapModels[location->GetRandomizerCheck()]).english;
break;
case 2:
jsonData["locations"][location->GetName()]["model"] =
ItemFromGIID(iceTrapModels[location->GetRandomizerCheck()]).GetName().french;
jsonData["locations"][location->GetName()]["trickName"] =
GetIceTrapName(iceTrapModels[location->GetRandomizerCheck()]).french;
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["model"] =
Rando::StaticData::ItemFromGIID(ctx->iceTrapModels[location->GetRandomizerCheck()]).GetName().french;
jsonData["locations"][Rando::StaticData::GetLocation(location->GetRandomizerCheck())->GetName()]["trickName"] =
GetIceTrapName(ctx->iceTrapModels[location->GetRandomizerCheck()]).french;
break;
}
}
}
}
//static void WriteHintData(int language) {
// for (auto [hintKey, item_location] : hintedLocations) {
// ItemLocation *hint_location = Location(hintKey);
// jsonData["hints"][hint_location->GetName()] = { { "text", hint_location->GetPlacedItemName().GetEnglish() },
// { "item", item_location->GetPlacedItemName().GetEnglish() },
// { "itemLocation", item_location->GetName() },
// { "locationArea", item_location->GetParentRegionKey() } };
// }
//}
const char* SpoilerLog_Write(int language) {
auto spoilerLog = tinyxml2::XMLDocument(false);
spoilerLog.InsertEndChild(spoilerLog.NewDeclaration());
@@ -884,14 +892,14 @@ const char* SpoilerLog_Write(int language) {
WritePlaythrough();
//WriteWayOfTheHeroLocation(spoilerLog);
playthroughLocations.clear();
playthroughBeatable = false;
wothLocations.clear();
auto ctx = Rando::Context::GetInstance();
ctx->playthroughLocations.clear();
ctx->playthroughBeatable = false;
ctx->wothLocations.clear();
WriteHints(language);
WriteShuffledEntrances();
WriteAllLocations(language);
//WriteHintData(language);
if (!std::filesystem::exists(LUS::Context::GetPathRelativeToAppDirectory("Randomizer"))) {
std::filesystem::create_directory(LUS::Context::GetPathRelativeToAppDirectory("Randomizer"));
@@ -914,6 +922,10 @@ const char* SpoilerLog_Write(int language) {
jsonFile << std::setw(4) << jsonString << std::endl;
jsonFile.close();
// Note: probably shouldn't return this without making sure this string is stored somewhere, but
// this return value is currently only used in playthrough.cpp as a true/false. Even if the pointer
// is no longer valid it would still not be nullptr if the spoilerfile was written, so it works but
// should probably be changed for correctness later on.
return fileName.c_str();
}

View File

@@ -29,7 +29,7 @@ typedef enum {
SPOILER_CHK_RANDOMIZER_INF,
} SpoilerCollectionCheckType;
// Location groups for checks, used to group the checks by logical location
// GetLocation groups for checks, used to group the checks by logical location
typedef enum {
GROUP_NO_GROUP,
GROUP_KOKIRI_FOREST, // 0x55, 0x28

View File

@@ -1,16 +1,16 @@
#include "starting_inventory.hpp"
#include "dungeon.hpp"
#include "item_list.hpp"
#include "settings.hpp"
#include "soh/Enhancements/randomizer/static_data.h"
using namespace Settings;
using namespace Dungeon;
std::vector<uint32_t> StartingInventory;
std::vector<RandomizerGet> StartingInventory;
uint8_t AdditionalHeartContainers;
static void AddItemToInventory(uint32_t item, size_t count = 1) {
static void AddItemToInventory(RandomizerGet item, size_t count = 1) {
StartingInventory.insert(StartingInventory.end(), count, item);
}
@@ -19,11 +19,11 @@ void GenerateStartingInventory() {
if (MapsAndCompasses.Is(MAPSANDCOMPASSES_START_WITH)) {
for (auto* dungeon : dungeonList) {
if (dungeon->GetMap() != NONE) {
if (dungeon->GetMap() != RG_NONE) {
AddItemToInventory(dungeon->GetMap());
}
if (dungeon->GetCompass() != NONE) {
if (dungeon->GetCompass() != RG_NONE) {
AddItemToInventory(dungeon->GetCompass());
}
}
@@ -42,123 +42,123 @@ void GenerateStartingInventory() {
// We can resolve this by starting with some extra keys
// - OoT Randomizer
if (SpiritTemple.IsMQ()) {
AddItemToInventory(SPIRIT_TEMPLE_SMALL_KEY, 3);
AddItemToInventory(RG_SPIRIT_TEMPLE_SMALL_KEY, 3);
}
}
if (BossKeysanity.Is(BOSSKEYSANITY_START_WITH)) {
AddItemToInventory(FOREST_TEMPLE_BOSS_KEY);
AddItemToInventory(FIRE_TEMPLE_BOSS_KEY);
AddItemToInventory(WATER_TEMPLE_BOSS_KEY);
AddItemToInventory(SPIRIT_TEMPLE_BOSS_KEY);
AddItemToInventory(SHADOW_TEMPLE_BOSS_KEY);
AddItemToInventory(RG_FOREST_TEMPLE_BOSS_KEY);
AddItemToInventory(RG_FIRE_TEMPLE_BOSS_KEY);
AddItemToInventory(RG_WATER_TEMPLE_BOSS_KEY);
AddItemToInventory(RG_SPIRIT_TEMPLE_BOSS_KEY);
AddItemToInventory(RG_SHADOW_TEMPLE_BOSS_KEY);
}
// Add Ganon's Boss key with Triforce Hunt so the game thinks it's obtainable from the start.
// During save init, the boss key isn't actually given and it's instead given when completing the triforce.
if (GanonsBossKey.Is(GANONSBOSSKEY_START_WITH) || GanonsBossKey.Is(GANONSBOSSKEY_TRIFORCE_HUNT)) {
AddItemToInventory(GANONS_CASTLE_BOSS_KEY);
AddItemToInventory(RG_GANONS_CASTLE_BOSS_KEY);
}
if (GerudoFortress.Is(GERUDOFORTRESS_OPEN) && !ShuffleGerudoToken) {
AddItemToInventory(GERUDO_MEMBERSHIP_CARD);
AddItemToInventory(RG_GERUDO_MEMBERSHIP_CARD);
}
//Starting Inventory Menu
//Values are associated so that the count of items matches the index of
//the option selected. If None is selected, the value will be zero and
//zero of the item will be added to the starting inventory.
AddItemToInventory(PROGRESSIVE_STICK_UPGRADE, StartingStickCapacity.Value<uint8_t>());
AddItemToInventory(PROGRESSIVE_NUT_UPGRADE, StartingNutCapacity.Value<uint8_t>());
AddItemToInventory(PROGRESSIVE_BOMB_BAG, StartingBombBag.Value<uint8_t>());
AddItemToInventory((BombchusInLogic ? PROGRESSIVE_BOMBCHUS : BOMBCHU_20), StartingBombchus.Value<uint8_t>());
AddItemToInventory(PROGRESSIVE_BOW, StartingBow.Value<uint8_t>());
AddItemToInventory(FIRE_ARROWS, StartingFireArrows.Value<uint8_t>());
AddItemToInventory(ICE_ARROWS, StartingIceArrows.Value<uint8_t>());
AddItemToInventory(LIGHT_ARROWS, StartingLightArrows.Value<uint8_t>());
AddItemToInventory(DINS_FIRE, StartingDinsFire.Value<uint8_t>());
AddItemToInventory(FARORES_WIND, StartingFaroresWind.Value<uint8_t>());
AddItemToInventory(NAYRUS_LOVE, StartingNayrusLove.Value<uint8_t>());
AddItemToInventory(PROGRESSIVE_SLINGSHOT, StartingSlingshot.Value<uint8_t>());
AddItemToInventory(BOOMERANG, StartingBoomerang.Value<uint8_t>());
AddItemToInventory(LENS_OF_TRUTH, StartingLensOfTruth.Value<uint8_t>());
AddItemToInventory(MAGIC_BEAN_PACK, StartingMagicBean.Value<uint8_t>());
AddItemToInventory(MEGATON_HAMMER, StartingMegatonHammer.Value<uint8_t>());
AddItemToInventory(PROGRESSIVE_HOOKSHOT, StartingHookshot.Value<uint8_t>());
AddItemToInventory(IRON_BOOTS, StartingIronBoots.Value<uint8_t>());
AddItemToInventory(HOVER_BOOTS, StartingHoverBoots.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_STICK_UPGRADE, StartingStickCapacity.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_NUT_UPGRADE, StartingNutCapacity.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_BOMB_BAG, StartingBombBag.Value<uint8_t>());
AddItemToInventory((BombchusInLogic ? RG_PROGRESSIVE_BOMBCHUS : RG_BOMBCHU_20), StartingBombchus.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_BOW, StartingBow.Value<uint8_t>());
AddItemToInventory(RG_FIRE_ARROWS, StartingFireArrows.Value<uint8_t>());
AddItemToInventory(RG_ICE_ARROWS, StartingIceArrows.Value<uint8_t>());
AddItemToInventory(RG_LIGHT_ARROWS, StartingLightArrows.Value<uint8_t>());
AddItemToInventory(RG_DINS_FIRE, StartingDinsFire.Value<uint8_t>());
AddItemToInventory(RG_FARORES_WIND, StartingFaroresWind.Value<uint8_t>());
AddItemToInventory(RG_NAYRUS_LOVE, StartingNayrusLove.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_SLINGSHOT, StartingSlingshot.Value<uint8_t>());
AddItemToInventory(RG_BOOMERANG, StartingBoomerang.Value<uint8_t>());
AddItemToInventory(RG_LENS_OF_TRUTH, StartingLensOfTruth.Value<uint8_t>());
AddItemToInventory(RG_MAGIC_BEAN_PACK, StartingMagicBean.Value<uint8_t>());
AddItemToInventory(RG_MEGATON_HAMMER, StartingMegatonHammer.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_HOOKSHOT, StartingHookshot.Value<uint8_t>());
AddItemToInventory(RG_IRON_BOOTS, StartingIronBoots.Value<uint8_t>());
AddItemToInventory(RG_HOVER_BOOTS, StartingHoverBoots.Value<uint8_t>());
//For starting bottles, we need to check if they are a big poe and add that if so
// since a big poe bottle is not logically equivalent to an empty bottle.
if (StartingBottle1.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
AddItemToInventory(BOTTLE_WITH_BIG_POE, 1);
AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
} else if (StartingBottle1.Value<uint8_t>()) {
AddItemToInventory(EMPTY_BOTTLE, 1);
AddItemToInventory(RG_EMPTY_BOTTLE, 1);
}
if (StartingBottle2.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
AddItemToInventory(BOTTLE_WITH_BIG_POE, 1);
AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
} else if (StartingBottle2.Value<uint8_t>()) {
AddItemToInventory(EMPTY_BOTTLE, 1);
AddItemToInventory(RG_EMPTY_BOTTLE, 1);
}
if (StartingBottle3.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
AddItemToInventory(BOTTLE_WITH_BIG_POE, 1);
AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
} else if (StartingBottle3.Value<uint8_t>()) {
AddItemToInventory(EMPTY_BOTTLE, 1);
AddItemToInventory(RG_EMPTY_BOTTLE, 1);
}
if (StartingBottle4.Value<uint8_t>() == STARTINGBOTTLE_BIG_POE) {
AddItemToInventory(BOTTLE_WITH_BIG_POE, 1);
AddItemToInventory(RG_BOTTLE_WITH_BIG_POE, 1);
} else if (StartingBottle4.Value<uint8_t>()) {
AddItemToInventory(EMPTY_BOTTLE, 1);
AddItemToInventory(RG_EMPTY_BOTTLE, 1);
}
AddItemToInventory(RUTOS_LETTER, StartingRutoBottle.Value<uint8_t>());
AddItemToInventory(PROGRESSIVE_OCARINA, StartingOcarina.Value<uint8_t>());
AddItemToInventory(ZELDAS_LULLABY, StartingZeldasLullaby.Value<uint8_t>());
AddItemToInventory(EPONAS_SONG, StartingEponasSong.Value<uint8_t>());
AddItemToInventory(SARIAS_SONG, StartingSariasSong.Value<uint8_t>());
AddItemToInventory(SUNS_SONG, StartingSunsSong.Value<uint8_t>());
AddItemToInventory(SONG_OF_TIME, StartingSongOfTime.Value<uint8_t>());
AddItemToInventory(SONG_OF_STORMS, StartingSongOfStorms.Value<uint8_t>());
AddItemToInventory(MINUET_OF_FOREST, StartingMinuetOfForest.Value<uint8_t>());
AddItemToInventory(BOLERO_OF_FIRE, StartingBoleroOfFire.Value<uint8_t>());
AddItemToInventory(SERENADE_OF_WATER, StartingSerenadeOfWater.Value<uint8_t>());
AddItemToInventory(REQUIEM_OF_SPIRIT, StartingRequiemOfSpirit.Value<uint8_t>());
AddItemToInventory(NOCTURNE_OF_SHADOW, StartingNocturneOfShadow.Value<uint8_t>());
AddItemToInventory(PRELUDE_OF_LIGHT, StartingPreludeOfLight.Value<uint8_t>());
AddItemToInventory(KOKIRI_SWORD, StartingKokiriSword.Value<uint8_t>());
AddItemToInventory(RG_RUTOS_LETTER, StartingRutoBottle.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_OCARINA, StartingOcarina.Value<uint8_t>());
AddItemToInventory(RG_ZELDAS_LULLABY, StartingZeldasLullaby.Value<uint8_t>());
AddItemToInventory(RG_EPONAS_SONG, StartingEponasSong.Value<uint8_t>());
AddItemToInventory(RG_SARIAS_SONG, StartingSariasSong.Value<uint8_t>());
AddItemToInventory(RG_SUNS_SONG, StartingSunsSong.Value<uint8_t>());
AddItemToInventory(RG_SONG_OF_TIME, StartingSongOfTime.Value<uint8_t>());
AddItemToInventory(RG_SONG_OF_STORMS, StartingSongOfStorms.Value<uint8_t>());
AddItemToInventory(RG_MINUET_OF_FOREST, StartingMinuetOfForest.Value<uint8_t>());
AddItemToInventory(RG_BOLERO_OF_FIRE, StartingBoleroOfFire.Value<uint8_t>());
AddItemToInventory(RG_SERENADE_OF_WATER, StartingSerenadeOfWater.Value<uint8_t>());
AddItemToInventory(RG_REQUIEM_OF_SPIRIT, StartingRequiemOfSpirit.Value<uint8_t>());
AddItemToInventory(RG_NOCTURNE_OF_SHADOW, StartingNocturneOfShadow.Value<uint8_t>());
AddItemToInventory(RG_PRELUDE_OF_LIGHT, StartingPreludeOfLight.Value<uint8_t>());
AddItemToInventory(RG_KOKIRI_SWORD, StartingKokiriSword.Value<uint8_t>());
if (ProgressiveGoronSword) {
AddItemToInventory(PROGRESSIVE_GORONSWORD, StartingBiggoronSword.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_GORONSWORD, StartingBiggoronSword.Value<uint8_t>());
} else {
AddItemToInventory(GIANTS_KNIFE, (StartingBiggoronSword.Is(STARTINGBGS_GIANTS_KNIFE)) ? 1 : 0);
AddItemToInventory(BIGGORON_SWORD, (StartingBiggoronSword.Is(STARTINGBGS_BIGGORON_SWORD)) ? 1 : 0);
AddItemToInventory(RG_GIANTS_KNIFE, (StartingBiggoronSword.Is(STARTINGBGS_GIANTS_KNIFE)) ? 1 : 0);
AddItemToInventory(RG_BIGGORON_SWORD, (StartingBiggoronSword.Is(STARTINGBGS_BIGGORON_SWORD)) ? 1 : 0);
}
AddItemToInventory(DEKU_SHIELD, StartingDekuShield.Value<uint8_t>());
AddItemToInventory(HYLIAN_SHIELD, StartingHylianShield.Value<uint8_t>());
AddItemToInventory(MIRROR_SHIELD, StartingMirrorShield.Value<uint8_t>());
AddItemToInventory(GORON_TUNIC, StartingGoronTunic.Value<uint8_t>());
AddItemToInventory(ZORA_TUNIC, StartingZoraTunic.Value<uint8_t>());
AddItemToInventory(PROGRESSIVE_MAGIC_METER, StartingMagicMeter.Value<uint8_t>());
AddItemToInventory(PROGRESSIVE_STRENGTH, StartingStrength.Value<uint8_t>());
AddItemToInventory(PROGRESSIVE_SCALE, StartingScale.Value<uint8_t>());
AddItemToInventory(PROGRESSIVE_WALLET, StartingWallet.Value<uint8_t>());
AddItemToInventory(STONE_OF_AGONY, StartingShardOfAgony.Value<uint8_t>());
AddItemToInventory(DOUBLE_DEFENSE, StartingDoubleDefense.Value<uint8_t>());
AddItemToInventory(KOKIRI_EMERALD, StartingKokiriEmerald.Value<uint8_t>());
AddItemToInventory(GORON_RUBY, StartingGoronRuby.Value<uint8_t>());
AddItemToInventory(ZORA_SAPPHIRE, StartingZoraSapphire.Value<uint8_t>());
AddItemToInventory(FOREST_MEDALLION, StartingForestMedallion.Value<uint8_t>());
AddItemToInventory(FIRE_MEDALLION, StartingFireMedallion.Value<uint8_t>());
AddItemToInventory(WATER_MEDALLION, StartingWaterMedallion.Value<uint8_t>());
AddItemToInventory(SPIRIT_MEDALLION, StartingSpiritMedallion.Value<uint8_t>());
AddItemToInventory(SHADOW_MEDALLION, StartingShadowMedallion.Value<uint8_t>());
AddItemToInventory(LIGHT_MEDALLION, StartingLightMedallion.Value<uint8_t>());
AddItemToInventory(GOLD_SKULLTULA_TOKEN, StartingSkulltulaToken.Value<uint8_t>());
AddItemToInventory(RG_DEKU_SHIELD, StartingDekuShield.Value<uint8_t>());
AddItemToInventory(RG_HYLIAN_SHIELD, StartingHylianShield.Value<uint8_t>());
AddItemToInventory(RG_MIRROR_SHIELD, StartingMirrorShield.Value<uint8_t>());
AddItemToInventory(RG_GORON_TUNIC, StartingGoronTunic.Value<uint8_t>());
AddItemToInventory(RG_ZORA_TUNIC, StartingZoraTunic.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_MAGIC_METER, StartingMagicMeter.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_STRENGTH, StartingStrength.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_SCALE, StartingScale.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_WALLET, StartingWallet.Value<uint8_t>());
AddItemToInventory(RG_STONE_OF_AGONY, StartingShardOfAgony.Value<uint8_t>());
AddItemToInventory(RG_DOUBLE_DEFENSE, StartingDoubleDefense.Value<uint8_t>());
AddItemToInventory(RG_KOKIRI_EMERALD, StartingKokiriEmerald.Value<uint8_t>());
AddItemToInventory(RG_GORON_RUBY, StartingGoronRuby.Value<uint8_t>());
AddItemToInventory(RG_ZORA_SAPPHIRE, StartingZoraSapphire.Value<uint8_t>());
AddItemToInventory(RG_FOREST_MEDALLION, StartingForestMedallion.Value<uint8_t>());
AddItemToInventory(RG_FIRE_MEDALLION, StartingFireMedallion.Value<uint8_t>());
AddItemToInventory(RG_WATER_MEDALLION, StartingWaterMedallion.Value<uint8_t>());
AddItemToInventory(RG_SPIRIT_MEDALLION, StartingSpiritMedallion.Value<uint8_t>());
AddItemToInventory(RG_SHADOW_MEDALLION, StartingShadowMedallion.Value<uint8_t>());
AddItemToInventory(RG_LIGHT_MEDALLION, StartingLightMedallion.Value<uint8_t>());
AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, StartingSkulltulaToken.Value<uint8_t>());
int8_t hearts = StartingHearts.Value<uint8_t>() - 2;
AdditionalHeartContainers = 0;
if (hearts < 0) {
AddItemToInventory(PIECE_OF_HEART, 4);
AddItemToInventory(RG_PIECE_OF_HEART, 4);
// Plentiful and minimal have less than 4 standard pieces of heart so also replace the winner heart
if (ItemPoolValue.Value<uint8_t>() == 0 || ItemPoolValue.Value<uint8_t>() == 3) {
AddItemToInventory(TREASURE_GAME_HEART);
AddItemToInventory(RG_TREASURE_GAME_HEART);
}
AdditionalHeartContainers = 1 - hearts;
@@ -167,28 +167,28 @@ void GenerateStartingInventory() {
uint8_t maxContainers = 8 * std::max(0, 2 - ItemPoolValue.Value<uint8_t>());
if (hearts <= maxContainers) {
AddItemToInventory(HEART_CONTAINER, hearts);
AddItemToInventory(RG_HEART_CONTAINER, hearts);
} else {
AddItemToInventory(HEART_CONTAINER, maxContainers);
AddItemToInventory(PIECE_OF_HEART, (hearts - maxContainers) * 4);
AddItemToInventory(RG_HEART_CONTAINER, maxContainers);
AddItemToInventory(RG_PIECE_OF_HEART, (hearts - maxContainers) * 4);
}
if (hearts == 17) {
AddItemToInventory(TREASURE_GAME_HEART);
AddItemToInventory(RG_TREASURE_GAME_HEART);
}
}
}
bool StartingInventoryHasBottle() {
uint32_t bottle = EMPTY_BOTTLE;
RandomizerGet bottle = RG_EMPTY_BOTTLE;
return ElementInContainer(bottle, StartingInventory);
}
void ApplyStartingInventory() {
for (uint32_t item : StartingInventory) {
if (item == PIECE_OF_HEART || item == HEART_CONTAINER || item == TREASURE_GAME_HEART)
for (RandomizerGet item : StartingInventory) {
if (item == RG_PIECE_OF_HEART || item == RG_HEART_CONTAINER || item == RG_TREASURE_GAME_HEART)
continue;
ItemTable(item).ApplyEffect();
Rando::StaticData::RetrieveItem(item).ApplyEffect();
}
}

View File

@@ -1,11 +1,11 @@
#pragma once
#include "keys.hpp"
#include "../randomizerTypes.h"
#include <vector>
#include <stdint.h>
extern std::vector<uint32_t> StartingInventory;
extern std::vector<RandomizerGet> StartingInventory;
extern uint8_t AdditionalHeartContainers;
void GenerateStartingInventory();

View File

@@ -0,0 +1,188 @@
#include "context.h"
#include "static_data.h"
#include "3drando/shops.hpp"
#include "3drando/dungeon.hpp"
#include <spdlog/spdlog.h>
namespace Rando {
std::weak_ptr<Context> Context::mContext;
Context::Context() {
for (int i = 0; i < RC_MAX; i++) {
itemLocationTable[i] = ItemLocation((RandomizerCheck)i);
}
}
std::shared_ptr<Context> Context::CreateInstance() {
if (mContext.expired()) {
auto instance = std::make_shared<Context>();
mContext = instance;
return instance;
}
return GetInstance();
}
std::shared_ptr<Context> Context::GetInstance() {
return mContext.lock();
}
Hint *Context::GetHint(RandomizerHintKey hintKey) {
return &hintTable[hintKey];
}
void Context::AddHint(RandomizerHintKey hintId, Text text, RandomizerCheck hintedLocation, HintType hintType,
Text hintedRegion) {
hintTable[hintId] = Hint(text, hintedLocation, hintType, hintedRegion);
GetItemLocation(hintedLocation)->SetHintKey(hintId);
}
ItemLocation *Context::GetItemLocation(RandomizerCheck locKey) {
return &(itemLocationTable[locKey]);
}
void Context::PlaceItemInLocation(RandomizerCheck locKey, RandomizerGet item, bool applyEffectImmediately,
bool setHidden) {
auto loc = GetItemLocation(locKey);
SPDLOG_DEBUG("\n");
SPDLOG_DEBUG(StaticData::RetrieveItem(item).GetName().GetEnglish());
SPDLOG_DEBUG(" placed at ");
SPDLOG_DEBUG(StaticData::GetLocation(locKey)->GetName());
SPDLOG_DEBUG("\n\n");
if (applyEffectImmediately || Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
Rando::StaticData::RetrieveItem(item).ApplyEffect();
}
//TODO? Show Progress
// If we're placing a non-shop item in a shop location, we want to record it for custom messages
if (StaticData::RetrieveItem(item).GetItemType() != ITEMTYPE_SHOP &&
Rando::StaticData::GetLocation(locKey)->IsCategory(Category::cShop)) {
int index = TransformShopIndex(GetShopIndex(locKey));
NonShopItems[index].Name = Rando::StaticData::RetrieveItem(item).GetName();
NonShopItems[index].Repurchaseable = Rando::StaticData::RetrieveItem(item).GetItemType() == ITEMTYPE_REFILL ||
Rando::StaticData::RetrieveItem(item).GetHintKey() == RHT_PROGRESSIVE_BOMBCHUS;
}
loc->SetPlacedItem(item);
if (setHidden) {
loc->SetHidden(true);
}
}
void Context::AddLocation(RandomizerCheck loc, std::vector<RandomizerCheck>* destination) {
if (destination == nullptr) {
destination = &allLocations;
}
destination->push_back(loc);
}
template<typename Container>
void Context::AddLocations(const Container& locations, std::vector<RandomizerCheck>* destination) {
if (destination == nullptr) {
destination = &allLocations;
}
destination->insert(destination->end(), std::cbegin(locations), std::cend(locations));
}
void Context::GenerateLocationPool() {
allLocations.clear();
AddLocation(RC_LINKS_POCKET);
if (Settings::TriforceHunt.Is(TRIFORCE_HUNT_ON)) {
AddLocation(RC_TRIFORCE_COMPLETED);
}
AddLocations(StaticData::overworldLocations);
for (auto dungeon : Dungeon::dungeonList) {
AddLocations(dungeon->GetDungeonLocations());
}
}
void Context::AddExcludedOptions() {
AddLocations(StaticData::overworldLocations, &everyPossibleLocation);
for (auto dungeon : Dungeon::dungeonList) {
AddLocations(dungeon->GetEveryLocation(), &everyPossibleLocation);
}
for (RandomizerCheck rc : everyPossibleLocation) {
GetItemLocation(rc)->AddExcludeOption();
}
}
std::vector<RandomizerCheck> Context::GetLocations(const std::vector<RandomizerCheck>& locationPool,
Category categoryInclude, Category categoryExclude) {
std::vector<RandomizerCheck> locationsInCategory;
for (RandomizerCheck locKey : locationPool) {
if (StaticData::GetLocation(locKey)->IsCategory(categoryInclude) &&
!StaticData::GetLocation(locKey)->IsCategory(categoryExclude)) {
locationsInCategory.push_back(locKey);
}
}
return locationsInCategory;
}
void Context::ItemReset() {
for (RandomizerCheck il : allLocations) {
GetItemLocation(il)->ResetVariables();
}
for (RandomizerCheck il : Rando::StaticData::dungeonRewardLocations) {
GetItemLocation(il)->ResetVariables();
}
}
void Context::LocationReset() {
for (RandomizerCheck il : allLocations) {
GetItemLocation(il)->RemoveFromPool();
}
for (RandomizerCheck il : Rando::StaticData::dungeonRewardLocations) {
GetItemLocation(il)->RemoveFromPool();
}
for (RandomizerCheck il : Rando::StaticData::gossipStoneLocations) {
GetItemLocation(il)->RemoveFromPool();
}
GetItemLocation(RC_GANONDORF_HINT)->RemoveFromPool();
}
void Context::HintReset() {
for (RandomizerCheck il : Rando::StaticData::gossipStoneLocations) {
GetItemLocation(il)->ResetVariables();
GetHint((RandomizerHintKey)(il - RC_DMC_GOSSIP_STONE + 1))->ResetVariables();
}
}
void Context::CreateItemOverrides() {
SPDLOG_DEBUG("NOW CREATING OVERRIDES\n\n");
for (RandomizerCheck locKey : allLocations) {
auto loc = Rando::StaticData::GetLocation(locKey);
auto itemLoc = GetItemLocation(locKey);
ItemOverride_Value val = Rando::StaticData::RetrieveItem(itemLoc->GetPlacedRandomizerGet()).Value();
// If this is an ice trap, store the disguise model in iceTrapModels
if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP) {
iceTrapModels[loc->GetRandomizerCheck()] = val.looksLikeItemId;
// If this is ice trap is in a shop, change the name based on what the model will look like
if (loc->IsCategory(Category::cShop)) {
NonShopItems[TransformShopIndex(GetShopIndex(locKey))].Name = GetIceTrapName(val.looksLikeItemId);
}
}
overrides.insert({
.key = itemLoc->Key(),
.value = val,
});
SPDLOG_DEBUG("\tScene: ");
SPDLOG_DEBUG(std::to_string(itemLoc->Key().scene));
SPDLOG_DEBUG("\tType: ");
SPDLOG_DEBUG(std::to_string(itemLoc->Key().type));
SPDLOG_DEBUG("\t");
SPDLOG_DEBUG(loc->GetName());
SPDLOG_DEBUG(": ");
SPDLOG_DEBUG(itemLoc->GetPlacedItemName().GetEnglish());
SPDLOG_DEBUG("\n");
}
SPDLOG_DEBUG("Overrides Created: ");
SPDLOG_DEBUG(std::to_string(overrides.size()));
}
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include "randomizerTypes.h"
#include "item_location.h"
#include "3drando/text.hpp"
#include "hint.h"
#include <memory>
#include <array>
/**
* @brief Singleton for storing and accessing dynamic Randomizer-related data
*
* The Context class is a class for storing and accessing dynamic Randomizer-related data.
* Dynamic Data, in this context, refers to data that can be different for each randomizer seed,
* i.e. item locations, hint contents and locations, settings, etc. This class is intended to be
* used as a Singleton.
*/
namespace Rando {
class Context {
public:
Context();
static std::shared_ptr<Context> CreateInstance();
static std::shared_ptr<Context> GetInstance();
Hint* GetHint(RandomizerHintKey hintKey);
void AddHint(RandomizerHintKey hintId, Text text, RandomizerCheck hintedLocation, HintType hintType,
Text hintedRegion);
ItemLocation* GetItemLocation(RandomizerCheck locKey);
void PlaceItemInLocation(RandomizerCheck locKey, RandomizerGet item, bool applyEffectImmediately = false,
bool setHidden = false);
std::vector<RandomizerCheck> allLocations;
void AddLocation(RandomizerCheck loc, std::vector<RandomizerCheck>* destination = nullptr);
template <typename Container>
void AddLocations(const Container& locations, std::vector<RandomizerCheck>* destination = nullptr);
void GenerateLocationPool();
std::vector<RandomizerCheck> GetLocations(const std::vector<RandomizerCheck>& locationPool,
Category categoryInclude, Category categoryExclude = Category::cNull);
void AddExcludedOptions();
void LocationReset();
void ItemReset();
void HintReset();
void CreateItemOverrides();
std::set<ItemOverride, ItemOverride_Compare> overrides = {};
std::vector<std::vector<RandomizerCheck>> playthroughLocations = {};
std::vector<RandomizerCheck> everyPossibleLocation = {};
std::vector<RandomizerCheck> wothLocations = {};
std::unordered_map<RandomizerCheck, uint8_t> iceTrapModels = {};
bool playthroughBeatable = false;
bool allLocationsReachable = false;
private:
static std::weak_ptr<Context> mContext;
std::array<Hint, RH_MAX> hintTable = {};
std::array<ItemLocation, RC_MAX> itemLocationTable = {};
};
} // namespace Rando

View File

@@ -158,7 +158,7 @@ extern "C" void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEnt
CLOSE_DISPS(play->state.gfxCtx);
}
extern "C" void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry getItemEntry) {
extern "C" void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry* getItemEntry) {
OPEN_DISPS(play->state.gfxCtx);
Gfx_SetupDL_25Xlu(play->state.gfxCtx);

View File

@@ -12,7 +12,7 @@ extern "C" {
void Randomizer_DrawSmallKey(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawKeyRing(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawBossKey(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry getItemEntry);
void Randomizer_DrawDoubleDefense(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawTriforcePiece(PlayState* play, GetItemEntry getItemEntry);
void Randomizer_DrawTriforcePieceGI(PlayState* play, GetItemEntry getItemEntry);
#ifdef __cplusplus

View File

@@ -0,0 +1,43 @@
#include "hint.h"
namespace Rando {
Hint::Hint() {}
Hint::Hint(Text text_): text(std::move(text_)) {}
Hint::Hint(Text text_, RandomizerCheck hintedLocation_, HintType hintType_, Text hintedRegion_)
: text(std::move(text_)), hintedLocation(hintedLocation_), hintType(hintType_),
hintedRegion(std::move(hintedRegion_)) {
}
const Text& Hint::GetText() const {
return text;
}
void Hint::SetHintedLocation(RandomizerCheck location) {
hintedLocation = location;
}
RandomizerCheck Hint::GetHintedLocation() {
return hintedLocation;
}
void Hint::SetHintType(HintType type) {
hintType = type;
}
HintType Hint::GetHintType() {
return hintType;
}
void Hint::SetHintedRegion(Text region) {
hintedRegion = region;
}
std::string Hint::GetHintedRegion() {
return hintedRegion.GetEnglish();
}
void Hint::ResetVariables() {
hintedLocation = RC_UNKNOWN_CHECK;
addedToPool = false;
}
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include "3drando/text.hpp"
#include "randomizerTypes.h"
namespace Rando {
class Hint {
public:
Hint();
Hint(Text text_);
Hint(Text text_, RandomizerCheck hintedLocation_, HintType hintType_, Text hintedRegion_);
const Text& GetText() const;
RandomizerCheck GetHintedLocation();
void SetHintedLocation (RandomizerCheck location);
HintType GetHintType();
void SetHintType (HintType type);
std::string GetHintedRegion();
void SetHintedRegion (Text region);
void ResetVariables();
bool IsAddedToPool();
void AddToPool();
private:
Text text;
RandomizerCheck hintedLocation;
HintType hintType;
Text hintedRegion;
bool addedToPool;
};
}

View File

@@ -0,0 +1,379 @@
#include "item.h"
#include "item_location.h"
#include "3drando/logic.hpp"
#include "3drando/random.hpp"
#include "3drando/item_pool.hpp"
#include "z64item.h"
#include "variables.h"
#include "macros.h"
#include "../../OTRGlobals.h"
namespace Rando {
Item::Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_,
bool* logicVar_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_,
uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_,
uint16_t modIndex_, bool progressive_, uint16_t price_)
: randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_),
advancement(advancement_), logicVar(logicVar_), hintKey(hintKey_), progressive(progressive_), price(price_) {
if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) {
giEntry = std::shared_ptr<GetItemEntry>(
new GetItemEntry(GET_ITEM(itemId_, objectId_, gid_, textId_, field_, chestAnimation_, category_, modIndex_,
(int16_t)randomizerGet_)));
} else {
giEntry = std::shared_ptr<GetItemEntry>(new GetItemEntry(
GET_ITEM(itemId_, objectId_, gid_, textId_, field_, chestAnimation_, category_, modIndex_, getItemId_)));
}
}
Item::Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_,
uint8_t* logicVar_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_,
uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_,
uint16_t modIndex_, bool progressive_, uint16_t price_)
: randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_),
advancement(advancement_), logicVar(logicVar_), hintKey(hintKey_), progressive(progressive_), price(price_) {
if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) {
giEntry = std::shared_ptr<GetItemEntry>(
new GetItemEntry(GET_ITEM(itemId_, objectId_, gid_, textId_, field_, chestAnimation_, category_, modIndex_,
(int16_t)randomizerGet_)));
} else {
giEntry = std::shared_ptr<GetItemEntry>(new GetItemEntry(
GET_ITEM(itemId_, objectId_, gid_, textId_, field_, chestAnimation_, category_, modIndex_, getItemId_)));
}
}
Item::Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int getItemId_, bool advancement_,
bool* logicVar_, RandomizerHintTextKey hintKey_, bool progressive_, uint16_t price_)
: randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_),
advancement(advancement_), logicVar(logicVar_), hintKey(hintKey_), progressive(progressive_), price(price_) {
}
Item::Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int getItemId_, bool advancement_,
uint8_t* logicVar_, RandomizerHintTextKey hintKey_, bool progressive_, uint16_t price_)
: randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_),
advancement(advancement_), logicVar(logicVar_), hintKey(hintKey_), progressive(progressive_), price(price_) {
}
Item::~Item() = default;
void Item::ApplyEffect() {
// If this is a key ring, logically add as many keys as we could need
if (RHT_FOREST_TEMPLE_KEY_RING <= hintKey && hintKey <= RHT_GANONS_CASTLE_KEY_RING) {
*std::get<uint8_t*>(logicVar) += 10;
} else {
if (std::holds_alternative<bool*>(logicVar)) {
*std::get<bool*>(logicVar) = true;
} else {
*std::get<uint8_t*>(logicVar) += 1;
}
}
Logic::UpdateHelpers();
}
void Item::UndoEffect() {
if (RHT_FOREST_TEMPLE_KEY_RING <= hintKey && hintKey <= RHT_GANONS_CASTLE_KEY_RING) {
*std::get<uint8_t*>(logicVar) -= 10;
} else {
if (std::holds_alternative<bool*>(logicVar)) {
*std::get<bool*>(logicVar) = false;
} else {
*std::get<uint8_t*>(logicVar) -= 1;
}
}
Logic::UpdateHelpers();
}
Rando::ItemOverride_Value Item::Value() const {
Rando::ItemOverride_Value val;
val.all = 0;
val.itemId = getItemId;
if (getItemId == RG_ICE_TRAP) {
val.looksLikeItemId = RandomElement(IceTrapModels);
}
if ((getItemId >= 0x95 && getItemId <= 0x9A)) { // Boss keys
val.looksLikeItemId = GI_KEY_BOSS;
}
if ((getItemId >= 0xAF && getItemId <= 0xB7)) { // Small keys
val.looksLikeItemId = GI_KEY_SMALL;
}
if (type == ITEMTYPE_SHOP) {
// With the current shopsanity implementation, we need a way to detect
// regular shop items. This method should have no unintended side effects
// unless there was a multiworld with 256 players... so, it should be fine.
val.player = 0xFF;
}
return val;
}
const Text& Item::GetName() const {
return name;
}
bool Item::IsAdvancement() const {
return advancement;
}
int Item::GetItemID() const {
return getItemId;
}
ItemType Item::GetItemType() const {
return type;
}
RandomizerGet Item::GetRandomizerGet() {
return randomizerGet;
}
uint16_t Item::GetPrice() const {
return price;
}
std::shared_ptr<GetItemEntry> Item::GetGIEntry() const {
if (giEntry != nullptr) {
return giEntry;
}
RandomizerGet actual = RG_NONE;
u8 numWallets =
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHOPSANITY) > RO_SHOPSANITY_ZERO_ITEMS ? 3 : 2;
switch (randomizerGet) {
case RG_PROGRESSIVE_STICK_UPGRADE:
switch (CUR_UPG_VALUE(UPG_STICKS)) {
case 0:
case 1:
actual = RG_DEKU_STICK_CAPACITY_20;
break;
case 2:
case 3:
actual = RG_DEKU_STICK_CAPACITY_30;
break;
}
break;
case RG_PROGRESSIVE_NUT_UPGRADE:
switch (CUR_UPG_VALUE(UPG_NUTS)) {
case 0:
case 1:
actual = RG_DEKU_NUT_CAPACITY_30;
break;
case 2:
case 3:
actual = RG_DEKU_NUT_CAPACITY_40;
break;
}
break;
case RG_PROGRESSIVE_BOMB_BAG:
switch (CUR_UPG_VALUE(UPG_BOMB_BAG)) {
case 0:
actual = RG_BOMB_BAG;
break;
case 1:
actual = RG_BIG_BOMB_BAG;
break;
case 2:
case 3:
actual = RG_BIGGEST_BOMB_BAG;
break;
}
break;
case RG_PROGRESSIVE_BOW:
switch (CUR_UPG_VALUE(UPG_QUIVER)) {
case 0:
actual = RG_FAIRY_BOW;
break;
case 1:
actual = RG_BIG_QUIVER;
break;
case 2:
case 3:
actual = RG_BIGGEST_QUIVER;
break;
}
break;
case RG_PROGRESSIVE_SLINGSHOT:
switch (CUR_UPG_VALUE(UPG_BULLET_BAG)) {
case 0:
actual = RG_FAIRY_SLINGSHOT;
break;
case 1:
actual = RG_BIG_BULLET_BAG;
break;
case 2:
case 3:
actual = RG_BIGGEST_BULLET_BAG;
break;
}
break;
case RG_PROGRESSIVE_OCARINA:
switch (INV_CONTENT(ITEM_OCARINA_FAIRY)) {
case ITEM_NONE:
actual = RG_FAIRY_OCARINA;
break;
case ITEM_OCARINA_FAIRY:
case ITEM_OCARINA_TIME:
actual = RG_OCARINA_OF_TIME;
break;
}
break;
case RG_PROGRESSIVE_HOOKSHOT:
switch (INV_CONTENT(ITEM_HOOKSHOT)) {
case ITEM_NONE:
actual = RG_HOOKSHOT;
break;
case ITEM_HOOKSHOT:
case ITEM_LONGSHOT:
actual = RG_LONGSHOT;
break;
}
break;
case RG_PROGRESSIVE_STRENGTH:
switch (CUR_UPG_VALUE(UPG_STRENGTH)) {
case 0:
actual = RG_GORONS_BRACELET;
break;
case 1:
actual = RG_SILVER_GAUNTLETS;
break;
case 2:
case 3:
actual = RG_GOLDEN_GAUNTLETS;
break;
}
break;
case RG_PROGRESSIVE_WALLET:
switch (CUR_UPG_VALUE(UPG_WALLET)) {
case 0:
actual = RG_ADULT_WALLET;
break;
case 1:
actual = RG_GIANT_WALLET;
break;
case 2:
case 3:
actual = numWallets == 3 ? RG_TYCOON_WALLET : RG_GIANT_WALLET;
break;
}
break;
case RG_PROGRESSIVE_SCALE:
switch (CUR_UPG_VALUE(UPG_SCALE)) {
case 0:
actual = RG_SILVER_SCALE;
break;
case 1:
case 2:
actual = RG_GOLDEN_SCALE;
break;
}
break;
case RG_PROGRESSIVE_MAGIC_METER:
switch (gSaveContext.magicLevel) {
case 0:
actual = RG_MAGIC_SINGLE;
break;
case 1:
case 2:
actual = RG_MAGIC_DOUBLE;
break;
}
break;
case RG_PROGRESSIVE_GORONSWORD: // todo progressive?
actual = RG_BIGGORON_SWORD;
break;
default:
actual = RG_NONE;
break;
}
return Rando::StaticData::RetrieveItem(actual).GetGIEntry();
}
GetItemEntry Item::GetGIEntry_Copy() {
return *GetGIEntry();
}
void Item::SetPrice(uint16_t price_) {
price = price_;
}
void Item::SetAsPlaythrough() {
playthrough = true;
}
void Item::SetCustomDrawFunc(CustomDrawFunc drawFunc) {
giEntry->drawFunc = drawFunc;
}
bool Item::IsPlaythrough() const {
return playthrough;
}
bool Item::IsBottleItem() const {
return getItemId == 0x0F || // Empty Bottle
getItemId == 0X14 || // Bottle with Milk
(getItemId >= 0x8C && getItemId <= 0x94); // Rest of bottled contents
}
bool Item::IsMajorItem() const {
using namespace Settings;
if (type == ITEMTYPE_TOKEN) {
return Bridge.Is(RAINBOWBRIDGE_TOKENS) || LACSCondition == LACSCONDITION_TOKENS;
}
if (type == ITEMTYPE_DROP || type == ITEMTYPE_EVENT || type == ITEMTYPE_SHOP || type == ITEMTYPE_MAP ||
type == ITEMTYPE_COMPASS) {
return false;
}
if (type == ITEMTYPE_DUNGEONREWARD && (ShuffleRewards.Is(REWARDSHUFFLE_END_OF_DUNGEON))) {
return false;
}
if ((randomizerGet == RG_BOMBCHU_5 || randomizerGet == RG_BOMBCHU_10 || randomizerGet == RG_BOMBCHU_20) &&
!BombchusInLogic) {
return false;
}
if (randomizerGet == RG_HEART_CONTAINER || randomizerGet == RG_PIECE_OF_HEART ||
randomizerGet == RG_TREASURE_GAME_HEART) {
return false;
}
if (type == ITEMTYPE_SMALLKEY && (Keysanity.Is(KEYSANITY_VANILLA) || Keysanity.Is(KEYSANITY_OWN_DUNGEON))) {
return false;
}
if (type == ITEMTYPE_FORTRESS_SMALLKEY && GerudoKeys.Is(GERUDOKEYS_VANILLA)) {
return false;
}
if ((type == ITEMTYPE_BOSSKEY && getItemId != 0xAD) &&
(BossKeysanity.Is(BOSSKEYSANITY_VANILLA) || BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON))) {
return false;
}
// Ganons Castle Boss Key
if (getItemId == 0xAD && (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA) || GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON))) {
return false;
}
if (randomizerGet == RG_GREG_RUPEE) {
return Bridge.Is(RAINBOWBRIDGE_GREG);
}
return IsAdvancement();
}
RandomizerHintTextKey Item::GetHintKey() const {
return hintKey;
}
const HintText& Item::GetHint() const {
return ::Hint(hintKey);
}
bool Item::operator==(const Item& right) const {
return type == right.GetItemType() && getItemId == right.GetItemID();
}
bool Item::operator!=(const Item& right) const {
return !operator==(right);
}
}

View File

@@ -0,0 +1,88 @@
#pragma once
#include <string>
#include <variant>
#include <memory>
#include "3drando/text.hpp"
#include "3drando/settings.hpp"
#include "3drando/hint_list.hpp"
#include "randomizerTypes.h"
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
namespace Rando {
union ItemOverride_Value;
}
enum ItemType {
ITEMTYPE_ITEM,
ITEMTYPE_MAP,
ITEMTYPE_COMPASS,
ITEMTYPE_BOSSKEY,
ITEMTYPE_SMALLKEY,
ITEMTYPE_TOKEN,
ITEMTYPE_FORTRESS_SMALLKEY,
ITEMTYPE_EVENT,
ITEMTYPE_DROP,
ITEMTYPE_REFILL,
ITEMTYPE_SONG,
ITEMTYPE_SHOP,
ITEMTYPE_DUNGEONREWARD
};
namespace Rando {
class Item {
public:
Item() = default;
Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_,
bool* logicVar_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_,
uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_,
uint16_t modIndex_, bool progressive = false, uint16_t price_ = 0);
Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_,
uint8_t* logicVar_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_,
uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_,
bool progressive = false, uint16_t price_ = 0);
Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int getItemId_, bool advancement_,
bool* logicVar_, RandomizerHintTextKey hintKey_, bool progressive = false, uint16_t price = 0);
Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int getItemId_, bool advancement_,
uint8_t* logicVar_, RandomizerHintTextKey hintKey_, bool progressive = false, uint16_t price = 0);
~Item();
void ApplyEffect();
void UndoEffect();
Rando::ItemOverride_Value Value() const;
const Text& GetName() const;
bool IsAdvancement() const;
int GetItemID() const;
ItemType GetItemType() const;
RandomizerGet GetRandomizerGet();
uint16_t GetPrice() const;
std::shared_ptr<GetItemEntry> GetGIEntry() const;
GetItemEntry GetGIEntry_Copy();
void SetPrice(uint16_t price_);
void SetAsPlaythrough();
void SetCustomDrawFunc(CustomDrawFunc);
bool IsPlaythrough() const;
bool IsBottleItem() const;
bool IsMajorItem() const;
RandomizerHintTextKey GetHintKey() const;
const HintText& GetHint() const;
bool operator==(const Item& right) const;
bool operator!=(const Item& right) const;
private:
RandomizerGet randomizerGet;
Text name;
ItemType type;
int16_t getItemId;
bool advancement;
std::variant<bool*, uint8_t*> logicVar;
RandomizerHintTextKey hintKey;
bool progressive = false;
uint16_t price;
bool playthrough = false;
std::shared_ptr<GetItemEntry> giEntry = nullptr;
};
}

View File

@@ -0,0 +1,295 @@
#include "static_data.h"
#include "3drando/logic.hpp"
#include "z64object.h"
#include "soh/Enhancements/custom-message/CustomMessageTypes.h"
#include "draw.h"
using namespace Rando;
std::array<Item, RG_MAX> Rando::StaticData::itemTable;
void Rando::StaticData::InitItemTable() {
itemTable[RG_NONE] = Item(RG_NONE, Text{ "No Item", "Rien", "Kein Artikel" }, ITEMTYPE_EVENT, GI_RUPEE_GREEN, false, &Logic::noVariable, RHT_NONE, ITEM_NONE, 0, 0, 0, 0, 0, ITEM_CATEGORY_JUNK, MOD_NONE);
// Randomizer Get Randomizer Get Name Text Type Get Item ID Adv. Logic Variable Hint Text Key Item ID Object ID Draw ID Text ID field Chest Animation Item Category Mod Index
itemTable[RG_KOKIRI_SWORD] = Item(RG_KOKIRI_SWORD, Text{ "Kokiri Sword", "Épée Kokiri", "Kokiri-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_KOKIRI, true, &Logic::KokiriSword, RHT_KOKIRI_SWORD, ITEM_SWORD_KOKIRI, OBJECT_GI_SWORD_1, GID_SWORD_KOKIRI, 0xA4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_GIANTS_KNIFE] = Item(RG_GIANTS_KNIFE, Text{ "Giant's Knife", "Lame des Géants", "Messer des Riesen" }, ITEMTYPE_ITEM, GI_SWORD_KNIFE, true, &Logic::KokiriSword, RHT_GIANTS_KNIFE, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x4B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BIGGORON_SWORD] = Item(RG_BIGGORON_SWORD, Text{ "Biggoron's Sword", "Épée de Biggoron", "Biggoron-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_BGS, true, &Logic::BiggoronSword, RHT_BIGGORON_SWORD, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x0C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_ITEM, GI_SHIELD_DEKU, false, &Logic::noVariable, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_ITEM, GI_SHIELD_HYLIAN, false, &Logic::noVariable, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegel-Schild" }, ITEMTYPE_ITEM, GI_SHIELD_MIRROR, true, &Logic::MirrorShield, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_ITEM, GI_TUNIC_GORON, true, &Logic::GoronTunic, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_ITEM, GI_TUNIC_ZORA, true, &Logic::ZoraTunic, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_ITEM, GI_BOOTS_IRON, true, &Logic::IronBoots, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_ITEM, GI_BOOTS_HOVER, true, &Logic::HoverBoots, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, &Logic::Boomerang, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, &Logic::LensOfTruth, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, &Logic::Hammer, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein der Qualen" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, &Logic::ShardOfAgony, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, &Logic::DinsFire, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, &Logic::FaroresWind, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, &Logic::NayrusLove, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrow", "Flèche de Feu", "Feuerpfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, &Logic::FireArrows, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrow", "Flèche de Glace", "Eispfeil" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, &Logic::IceArrows, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrow", "Flèche de Lumière", "Lichtpfeil" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, &Logic::LightArrows, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo Karte" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, &Logic::GerudoToken, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, &Logic::MagicBean, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, &Logic::MagicBeanPack, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_DOUBLE_DEFENSE] = Item(RG_DOUBLE_DEFENSE, Text{ "Double Defense", "Double Défence", "Doppelte Verteidigung" }, ITEMTYPE_ITEM, RG_DOUBLE_DEFENSE, true, &Logic::DoubleDefense, RHT_DOUBLE_DEFENSE, RG_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER,0xE9, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_DOUBLE_DEFENSE].SetCustomDrawFunc(Randomizer_DrawDoubleDefense);
// Trade Quest Items
itemTable[RG_WEIRD_EGG] = Item(RG_WEIRD_EGG, Text{ "Weird Egg", "Oeuf Curieux", "Seltsames Ei" }, ITEMTYPE_ITEM, GI_WEIRD_EGG, true, &Logic::WeirdEgg, RHT_WEIRD_EGG, ITEM_WEIRD_EGG, OBJECT_GI_EGG, GID_EGG, 0x9A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_ZELDAS_LETTER] = Item(RG_ZELDAS_LETTER, Text{ "Zelda's Letter", "Lettre de Zelda", "Zeldas Brief" }, ITEMTYPE_ITEM, GI_LETTER_ZELDA, true, &Logic::ZeldasLetter, RHT_ZELDAS_LETTER, ITEM_LETTER_ZELDA, OBJECT_GI_LETTER, GID_LETTER_ZELDA, 0x69, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_POCKET_EGG] = Item(RG_POCKET_EGG, Text{ "Pocket Egg", "Oeuf de poche", "Taschenei" }, ITEMTYPE_ITEM, GI_POCKET_EGG, true, &Logic::PocketEgg, RHT_POCKET_EGG, ITEM_POCKET_EGG, OBJECT_GI_EGG, GID_EGG, 0x01, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_COJIRO] = Item(RG_COJIRO, Text{ "Cojiro", "P'tit Poulet", "Cojiro" }, ITEMTYPE_ITEM, GI_COJIRO, true, &Logic::Cojiro, RHT_COJIRO, ITEM_COJIRO, OBJECT_GI_NIWATORI, GID_COJIRO, 0x02, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champigon Suspect", "Seltsamer Pilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, &Logic::OddMushroom, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_ODD_POTION] = Item(RG_ODD_POTION, Text{ "Odd Potion", "Mixture Suspecte", "Seltsamer Trank" }, ITEMTYPE_ITEM, GI_ODD_POTION, true, &Logic::OddPoultice, RHT_ODD_POTION, ITEM_ODD_POTION, OBJECT_GI_POWDER, GID_ODD_POTION, 0x04, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_POACHERS_SAW] = Item(RG_POACHERS_SAW, Text{ "Poacher's Saw", "Scie du Chasseur", "Wilderer-Säge" }, ITEMTYPE_ITEM, GI_SAW, true, &Logic::PoachersSaw, RHT_POACHERS_SAW, ITEM_SAW, OBJECT_GI_SAW, GID_SAW, 0x05, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "Schwert des gebrochenen Goronen" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, &Logic::BrokenSword, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_PRESCRIPTION] = Item(RG_PRESCRIPTION, Text{ "Prescription", "Ordonnance", "Verschreibung" }, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, &Logic::Prescription, RHT_PRESCRIPTION, ITEM_PRESCRIPTION, OBJECT_GI_PRESCRIPTION, GID_PRESCRIPTION, 0x09, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_EYEBALL_FROG] = Item(RG_EYEBALL_FROG, Text{ "Eyeball Frog", "Crapaud-qui-louche", "Augapfel-Frosch" }, ITEMTYPE_ITEM, GI_FROG, true, &Logic::EyeballFrog, RHT_EYEBALL_FROG, ITEM_FROG, OBJECT_GI_FROG, GID_FROG, 0x0D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_EYEDROPS] = Item(RG_EYEDROPS, Text{ "World's Finest Eyedrops", "Super Gouttes", "Supertropfen" }, ITEMTYPE_ITEM, GI_EYEDROPS, true, &Logic::Eyedrops, RHT_EYEDROPS, ITEM_EYEDROPS, OBJECT_GI_EYE_LOTION, GID_EYEDROPS, 0x0E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_CLAIM_CHECK] = Item(RG_CLAIM_CHECK, Text{ "Claim Check", "Certificat", "Quittung" }, ITEMTYPE_ITEM, GI_CLAIM_CHECK, true, &Logic::ClaimCheck, RHT_CLAIM_CHECK, ITEM_CLAIM_CHECK, OBJECT_GI_TICKETSTONE, GID_CLAIM_CHECK, 0x0A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
// Skulltula Token
itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, &Logic::GoldSkulltulaTokens, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE);
// Progressive Items
itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, &Logic::ProgressiveHookshot, RHT_PROGRESSIVE_HOOKSHOT, true);
itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, &Logic::ProgressiveStrength, RHT_PROGRESSIVE_STRENGTH, true);
itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, &Logic::ProgressiveBombBag, RHT_PROGRESSIVE_BOMB_BAG, true);
itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, &Logic::ProgressiveBow, RHT_PROGRESSIVE_BOW, true);
itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, &Logic::ProgressiveBulletBag,RHT_PROGRESSIVE_SLINGSHOT, true);
itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Brieftasche" }, ITEMTYPE_ITEM, 0x85, true, &Logic::ProgressiveWallet, RHT_PROGRESSIVE_WALLET, true);
itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Skala" }, ITEMTYPE_ITEM, 0x86, true, &Logic::ProgressiveScale, RHT_PROGRESSIVE_SCALE, true);
itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nusskapazität" }, ITEMTYPE_ITEM, 0x87, false, &Logic::noVariable, RHT_PROGRESSIVE_NUT_UPGRADE, true);
itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stick-Kapazität" }, ITEMTYPE_ITEM, 0x88, false, &Logic::noVariable, RHT_PROGRESSIVE_STICK_UPGRADE, true);
itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Kriechgrube" }, ITEMTYPE_ITEM, 0x89, true, &Logic::Bombchus, RHT_PROGRESSIVE_BOMBCHUS, RG_PROGRESSIVE_BOMBCHUS, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, true);
itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, &Logic::ProgressiveMagic, RHT_PROGRESSIVE_MAGIC_METER, true);
itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, &Logic::ProgressiveOcarina, RHT_PROGRESSIVE_OCARINA, true);
itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronenschwert" }, ITEMTYPE_ITEM, 0xD4, true, &Logic::ProgressiveGiantKnife,RHT_PROGRESSIVE_GORONSWORD, true);
// Bottles
itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, &Logic::Bottles, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, &Logic::Bottles, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, &Logic::Bottles, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, &Logic::Bottles, RHT_BOTTLE_WITH_GREEN_POTION,RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, &Logic::Bottles, RHT_BOTTLE_WITH_BLUE_POTION,RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, &Logic::Bottles, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, &Logic::Bottles, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, &Logic::Bottles, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOTTLE_WITH_BUGS] = Item(RG_BOTTLE_WITH_BUGS, Text{ "Bottle with Bugs", "Bouteille avec des Insectes", "Flasche mit Wanzen" }, ITEMTYPE_ITEM, 0x92, true, &Logic::Bottles, RHT_BOTTLE_WITH_BUGS, RG_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BOTTLE_WITH_POE] = Item(RG_BOTTLE_WITH_POE, Text{ "Bottle with Poe", "Bouteille avec un Esprit", "Flasche mit einem Geist" }, ITEMTYPE_ITEM, 0x94, true, &Logic::Bottles, RHT_BOTTLE_WITH_POE, RG_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, &Logic::RutosLetter, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER,GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, &Logic::BottleWithBigPoe, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
// Songs
itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, &Logic::ZeldasLullaby, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, &Logic::EponasSong, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Sarias Lied" }, ITEMTYPE_SONG, 0xC3, true, &Logic::SariasSong, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Das Lied der Sonne" }, ITEMTYPE_SONG, 0xC4, true, &Logic::SunsSong, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Das Lied der Zeit" }, ITEMTYPE_SONG, 0xC5, true, &Logic::SongOfTime, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Lied der Stürme" }, ITEMTYPE_SONG, 0xC6, true, &Logic::SongOfStorms, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Wald-Minuett" }, ITEMTYPE_SONG, 0xBB, true, &Logic::MinuetOfForest, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, &Logic::BoleroOfFire, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, &Logic::SerenadeOfWater, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne der Schatten " }, ITEMTYPE_SONG, 0xBF, true, &Logic::NocturneOfShadow, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem des Geistes" }, ITEMTYPE_SONG, 0xBE, true, &Logic::RequiemOfSpirit, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Präludium des Lichts" }, ITEMTYPE_SONG, 0xC0, true, &Logic::PreludeOfLight, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
// Maps and Compasses
itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, &Logic::noVariable, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, &Logic::noVariable, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, &Logic::noVariable, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Waldtempel Karte" }, ITEMTYPE_MAP, 0xA8, false, &Logic::noVariable, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Feuertempel Karte" }, ITEMTYPE_MAP, 0xA9, false, &Logic::noVariable, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Wassertempel-Karte" }, ITEMTYPE_MAP, 0xAA, false, &Logic::noVariable, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Geistertempel Karte" }, ITEMTYPE_MAP, 0xAB, false, &Logic::noVariable, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, &Logic::noVariable, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Boden des Brunnens Karte" }, ITEMTYPE_MAP, 0xAD, false, &Logic::noVariable, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Eishöhle Karte" }, ITEMTYPE_MAP, 0xAE, false, &Logic::noVariable, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompass des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, &Logic::noVariable, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompass der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, &Logic::noVariable, RHT_DODONGOS_CAVERN_COMPASS,RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompass des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, &Logic::noVariable, RHT_JABU_JABUS_BELLY_COMPASS,RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Waldtempel-Kompass" }, ITEMTYPE_COMPASS, 0x9E, false, &Logic::noVariable, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Feuertempel-Kompass" }, ITEMTYPE_COMPASS, 0x9F, false, &Logic::noVariable, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Wassertempel-Kompass" }, ITEMTYPE_COMPASS, 0xA0, false, &Logic::noVariable, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Geistiger Tempelkompass" }, ITEMTYPE_COMPASS, 0xA1, false, &Logic::noVariable, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompass des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, &Logic::noVariable, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Boden des Brunnenkompasses" }, ITEMTYPE_COMPASS, 0xA3, false, &Logic::noVariable, RHT_BOTTOM_OF_THE_WELL_COMPASS,RG_BOTTOM_OF_THE_WELL_COMPASS,OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Eishöhlenkompass" }, ITEMTYPE_COMPASS, 0xA4, false, &Logic::noVariable, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
// Boss Keys
itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Waldtempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x95, true, &Logic::BossKeyForestTemple, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER);
itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey);
itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Feuertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x96, true, &Logic::BossKeyFireTemple, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER);
itemTable[RG_FIRE_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey);
itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Wassertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x97, true, &Logic::BossKeyWaterTemple, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER);
itemTable[RG_WATER_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey);
itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Geistertempel-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x98, true, &Logic::BossKeySpiritTemple, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER);
itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey);
itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Schlüssel für den Boss des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, &Logic::BossKeyShadowTemple, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER);
itemTable[RG_SHADOW_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey);
itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Ganons Schloss-Boss-Schlüssel" }, ITEMTYPE_BOSSKEY, 0x9A, true, &Logic::BossKeyGanonsCastle, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER);
itemTable[RG_GANONS_CASTLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey);
itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Waldtempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xAF, true, &Logic::ForestTempleKeys, RHT_FOREST_TEMPLE_SMALL_KEY,RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_FOREST_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Feuertempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB0, true, &Logic::FireTempleKeys, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_FIRE_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Wassertempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB1, true, &Logic::WaterTempleKeys, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_WATER_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Geisttempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB2, true, &Logic::SpiritTempleKeys, RHT_SPIRIT_TEMPLE_SMALL_KEY,RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Schattentempel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB3, true, &Logic::ShadowTempleKeys, RHT_SHADOW_TEMPLE_SMALL_KEY,RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_SHADOW_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Boden des Brunnens Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB4, true, &Logic::BottomOfTheWellKeys, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY,RG_BOTTOM_OF_THE_WELL_SMALL_KEY,OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, Text{ "Training Grounds Small Key", "Petite Clé du Gymnase Gerudo", "Trainingsgelände Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB5, true, &Logic::GerudoTrainingGroundsKeys, RHT_GERUDO_TRAINING_GROUNDS_SMALL_KEY,RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY,OBJECT_GI_KEY,GID_KEY_SMALL,TEXT_RANDOMIZER_CUSTOM_ITEM,0x80, CHEST_ANIM_SHORT,ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Gerudo-Festung Kleiner Schlüssel" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, &Logic::GerudoFortressKeys, RHT_GERUDO_FORTRESS_SMALL_KEY,RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_GERUDO_FORTRESS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Ganons Schloss Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xB7, true, &Logic::GanonsCastleKeys, RHT_GANONS_CASTLE_SMALL_KEY,RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Truhenspiel Kleiner Schlüssel" }, ITEMTYPE_SMALLKEY, 0xDE, true, &Logic::TreasureGameKeys, RHT_TREASURE_GAME_SMALL_KEY,RG_TREASURE_GAME_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
// Key Rings
itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Waldtempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD5, true, &Logic::ForestTempleKeys, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Feuertempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD6, true, &Logic::FireTempleKeys, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_FIRE_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Wassertempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD7, true, &Logic::WaterTempleKeys, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_WATER_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Geisttempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD8, true, &Logic::SpiritTempleKeys, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_SPIRIT_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schattentempel Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xD9, true, &Logic::ShadowTempleKeys, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_SHADOW_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Boden des Brunnens Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDA, true, &Logic::BottomOfTheWellKeys, RHT_BOTTOM_OF_THE_WELL_KEY_RING,RG_BOTTOM_OF_THE_WELL_KEY_RING,OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
itemTable[RG_GERUDO_TRAINING_GROUNDS_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUNDS_KEY_RING, Text{ "Training Grounds Key Ring", "Trousseau du Gymnase Gerudo", "Trainingsgelände Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDB, true, &Logic::GerudoTrainingGroundsKeys, RHT_GERUDO_TRAINING_GROUNDS_KEY_RING,RG_GERUDO_TRAINING_GROUNDS_KEY_RING,OBJECT_GI_KEY,GID_KEY_SMALL,TEXT_RANDOMIZER_CUSTOM_ITEM,0x80, CHEST_ANIM_SHORT,ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_GERUDO_TRAINING_GROUNDS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Gerudo Festung Schlüsselanhänger" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, &Logic::GerudoFortressKeys, RHT_GERUDO_FORTRESS_KEY_RING,RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_GERUDO_FORTRESS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Ganons Schloss Schlüsselanhänger" }, ITEMTYPE_SMALLKEY, 0xDD, true, &Logic::GanonsCastleKeys, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_GANONS_CASTLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
// Dungeon Rewards
itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, &Logic::KokiriEmerald, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, &Logic::GoronRuby, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, &Logic::ZoraSapphire, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Wald Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, &Logic::ForestMedallion, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST,0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Feuer Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, &Logic::FireMedallion, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Wasser Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, &Logic::WaterMedallion, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER,0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Geist Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, &Logic::SpiritMedallion, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT,0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Schatten Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, &Logic::ShadowMedallion, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW,0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Licht Medaillon" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, &Logic::LightMedallion, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT,0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
// Generic Items
itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, &Logic::noVariable, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüne Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, &Logic::noVariable, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_GREG_RUPEE] = Item(RG_GREG_RUPEE, Text{ "Greg the Green Rupee", "Rubis Greg", "Greg Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, true, &Logic::Greg, RHT_GREG_RUPEE, RG_GREG_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blaue Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, &Logic::noVariable, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Rote Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, &Logic::noVariable, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Lila Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, &Logic::noVariable, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesige Rupie" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, &Logic::noVariable, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, &Logic::PieceOfHeart, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herz-Container" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2,true, &Logic::HeartContainer, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER,0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_ICE_TRAP] = Item(RG_ICE_TRAP, Text{ "Ice Trap", "Piège de Glace", "Eisfalle" }, ITEMTYPE_ITEM, RG_ICE_TRAP, false, &Logic::noVariable, RHT_ICE_TRAP, RG_ICE_TRAP, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_MILK] = Item(RG_MILK, Text{ "Milk", "Lait", "Milch" }, ITEMTYPE_ITEM, GI_MILK, false, &Logic::noVariable, RHT_NONE, ITEM_MILK, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE);
// Refills
itemTable[RG_BOMBS_5] = Item(RG_BOMBS_5, Text{ "Bombs (5)", "Bombes (5)", "Bomben (5)" }, ITEMTYPE_REFILL, GI_BOMBS_5, false, &Logic::noVariable, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_BOMBS_10] = Item(RG_BOMBS_10, Text{ "Bombs (10)", "Bombes (10)", "Bomben (10)" }, ITEMTYPE_REFILL, GI_BOMBS_10, false, &Logic::noVariable, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_BOMBS_20] = Item(RG_BOMBS_20, Text{ "Bombs (20)", "Bombes (20)", "Bomben (20)" }, ITEMTYPE_REFILL, GI_BOMBS_20, false, &Logic::noVariable, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_BOMBCHU_5] = Item(RG_BOMBCHU_5, Text{ "Bombchus (5)", "Missiles (5)", "Bombchus (5)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_5, true, &Logic::Bombchus5, RHT_BOMBCHU_5, ITEM_BOMBCHUS_5, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_BOMBCHU_10] = Item(RG_BOMBCHU_10, Text{ "Bombchus (10)", "Missiles (10)", "Bombchus (10)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_10, true, &Logic::Bombchus10, RHT_BOMBCHU_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_BOMBCHU_20] = Item(RG_BOMBCHU_20, Text{ "Bombchus (20)", "Missiles (20)", "Bombchus (20)" }, ITEMTYPE_REFILL, GI_BOMBCHUS_20, true, &Logic::Bombchus20, RHT_BOMBCHU_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_BOMBCHU_DROP] = Item(RG_BOMBCHU_DROP, Text{ "Bombchu Drop", "Drop Missiles", "Bombchus" }, ITEMTYPE_DROP, GI_BOMBCHUS_10, true, &Logic::BombchuDrop, RHT_NONE, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_ARROWS_5] = Item(RG_ARROWS_5, Text{ "Arrows (5)", "Flèches (5)", "Pfeile (5)" }, ITEMTYPE_REFILL, GI_ARROWS_SMALL, false, &Logic::noVariable, RHT_ARROWS_5, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_ARROWS_10] = Item(RG_ARROWS_10, Text{ "Arrows (10)", "Flèches (10)", "Pfeile (10)" }, ITEMTYPE_REFILL, GI_ARROWS_MEDIUM, false, &Logic::noVariable, RHT_ARROWS_10, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_ARROWS_30] = Item(RG_ARROWS_30, Text{ "Arrows (30)", "Flèches (30)", "Pfeile (30)" }, ITEMTYPE_REFILL, GI_ARROWS_LARGE, false, &Logic::noVariable, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_DEKU_NUTS_5] = Item(RG_DEKU_NUTS_5, Text{ "Deku Nuts (5)", "Noix Mojo (5)", "Deku-Nüsse (5)" }, ITEMTYPE_REFILL, GI_NUTS_5, false, &Logic::noVariable, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_DEKU_NUTS_10] = Item(RG_DEKU_NUTS_10, Text{ "Deku Nuts (10)", "Noix Mojo (10)", "Deku-Nüsse (10)" }, ITEMTYPE_REFILL, GI_NUTS_10, false, &Logic::noVariable, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_DEKU_SEEDS_30] = Item(RG_DEKU_SEEDS_30, Text{ "Deku Seeds (30)", "Graines Mojo (30)", "Deku-Samen (30)" }, ITEMTYPE_REFILL, GI_SEEDS_30, false, &Logic::noVariable, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stick (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, &Logic::noVariable, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Rotes Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_RED, false, &Logic::noVariable, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Grünes Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, &Logic::noVariable, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE);
itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Blaues Elixier Nachfüllpackung" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, &Logic::noVariable, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE);
// Treasure Game
itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhen-Minispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, &Logic::PieceOfHeart, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüne Rupie (Schatztruhe-Minispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE,false, &Logic::noVariable, RHT_TREASURE_GAME_GREEN_RUPEE,ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE);
// Shop
itemTable[RG_BUY_DEKU_NUT_5] = Item(RG_BUY_DEKU_NUT_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuss kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, &Logic::Nuts, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 15);
itemTable[RG_BUY_ARROWS_30] = Item(RG_BUY_ARROWS_30, Text{ "Buy Arrows (30)", "Acheter: Flèches (30)", "Pfeile kaufen (30)" }, ITEMTYPE_SHOP, GI_ARROWS_MEDIUM, true, &Logic::BuyArrow, RHT_ARROWS_30, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 60);
itemTable[RG_BUY_ARROWS_50] = Item(RG_BUY_ARROWS_50, Text{ "Buy Arrows (50)", "Acheter: Flèches (50)", "Pfeile kaufen (50)" }, ITEMTYPE_SHOP, GI_ARROWS_LARGE, true, &Logic::BuyArrow, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 90);
itemTable[RG_BUY_BOMBS_525] = Item(RG_BUY_BOMBS_525, Text{ "Buy Bombs (5) [25]", "Acheter: Bombes (5) [25]", "Bomben kaufen (5) [25]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, &Logic::BuyBomb, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 25);
itemTable[RG_BUY_DEKU_NUT_10] = Item(RG_BUY_DEKU_NUT_10, Text{ "Buy Deku Nut (10)", "Acheter: Noix Mojo (10)", "Deku-Nuss kaufen (10)" }, ITEMTYPE_SHOP, GI_NUTS_10, true, &Logic::Nuts, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30);
itemTable[RG_BUY_DEKU_STICK_1] = Item(RG_BUY_DEKU_STICK_1, Text{ "Buy Deku Stick (1)", "Acheter: Bâton Mojo (1)", "Deku-Stick kaufen (1)" }, ITEMTYPE_SHOP, GI_STICKS_1, true, &Logic::Sticks, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10);
itemTable[RG_BUY_BOMBS_10] = Item(RG_BUY_BOMBS_10, Text{ "Buy Bombs (10)", "Acheter: Bombes (10)", "Bomben kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBS_10, true, &Logic::BuyBomb, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50);
itemTable[RG_BUY_FISH] = Item(RG_BUY_FISH, Text{ "Buy Fish", "Acheter: Poisson", "Fisch kaufen" }, ITEMTYPE_SHOP, GI_FISH, true, &Logic::FishAccess, RHT_BOTTLE_WITH_FISH, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 200);
itemTable[RG_BUY_RED_POTION_30] = Item(RG_BUY_RED_POTION_30, Text{ "Buy Red Potion [30]", "Acheter: Potion Rouge [30]", "Rotes Elixier kaufen [30]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, &Logic::noVariable, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30);
itemTable[RG_BUY_GREEN_POTION] = Item(RG_BUY_GREEN_POTION, Text{ "Buy Green Potion", "Acheter: Potion Verte", "Grünes Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_GREEN, true, &Logic::BuyGPotion, RHT_BOTTLE_WITH_GREEN_POTION,ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30);
itemTable[RG_BUY_BLUE_POTION] = Item(RG_BUY_BLUE_POTION, Text{ "Buy Blue Potion", "Acheter: Potion Bleue", "Blaues Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_BLUE, true, &Logic::BuyBPotion, RHT_BOTTLE_WITH_BLUE_POTION,ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 100);
itemTable[RG_BUY_HYLIAN_SHIELD] = Item(RG_BUY_HYLIAN_SHIELD, Text{ "Buy Hylian Shield", "Acheter: Bouclier Hylien", "Hylianischer Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_HYLIAN, true, &Logic::HylianShield, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 80);
itemTable[RG_BUY_DEKU_SHIELD] = Item(RG_BUY_DEKU_SHIELD, Text{ "Buy Deku Shield", "Acheter: Bouclier Mojo", "Deku-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_DEKU, true, &Logic::DekuShield, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 40);
itemTable[RG_BUY_GORON_TUNIC] = Item(RG_BUY_GORON_TUNIC, Text{ "Buy Goron Tunic", "Acheter: Tunique Goron", "Goronen-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_GORON, true, &Logic::GoronTunic, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 200);
itemTable[RG_BUY_ZORA_TUNIC] = Item(RG_BUY_ZORA_TUNIC, Text{ "Buy Zora Tunic", "Acheter: Tunique Zora", "Zora-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_ZORA, true, &Logic::ZoraTunic, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 300);
itemTable[RG_BUY_HEART] = Item(RG_BUY_HEART, Text{ "Buy Heart", "Acheter: Coeur de Vie", "Herz kaufen" }, ITEMTYPE_SHOP, GI_HEART, false, &Logic::noVariable, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10);
itemTable[RG_BUY_BOMBCHU_10] = Item(RG_BUY_BOMBCHU_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Bomchu kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, &Logic::BuyBombchus10, RHT_BOMBCHU_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 99);
itemTable[RG_BUY_BOMBCHU_20] = Item(RG_BUY_BOMBCHU_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Bomchu kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, &Logic::BuyBombchus20, RHT_BOMBCHU_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 180);
itemTable[RG_BUY_DEKU_SEEDS_30] = Item(RG_BUY_DEKU_SEEDS_30, Text{ "Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Deku-Samen kaufen (30)" }, ITEMTYPE_SHOP, GI_SEEDS_30, true, &Logic::BuySeed, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30);
itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, &Logic::noVariable, RHT_NONE, false, 0);
itemTable[RG_BUY_BLUE_FIRE] = Item(RG_BUY_BLUE_FIRE, Text{ "Buy Blue Fire", "Acheter: Flamme Bleue", "Blaues Feuer kaufen" }, ITEMTYPE_SHOP, GI_BLUE_FIRE, true, &Logic::BlueFireAccess, RHT_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 300);
itemTable[RG_BUY_BOTTLE_BUG] = Item(RG_BUY_BOTTLE_BUG, Text{ "Buy Bottle Bug", "Acheter: Insecte en bouteille", "Flaschenkäfer kaufen" }, ITEMTYPE_SHOP, GI_BUGS, true, &Logic::BugsAccess, RHT_BOTTLE_WITH_BUGS, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50);
itemTable[RG_BUY_POE] = Item(RG_BUY_POE, Text{ "Buy Poe", "Acheter: Esprit", "Geist kaufen" }, ITEMTYPE_SHOP, RG_BUY_POE, false, &Logic::noVariable, RHT_BOTTLE_WITH_BIG_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30);
itemTable[RG_BUY_FAIRYS_SPIRIT] = Item(RG_BUY_FAIRYS_SPIRIT, Text{ "Buy Fairy's Spirit", "Acheter: Esprit de Fée", "Feengeist kaufen" }, ITEMTYPE_SHOP, GI_FAIRY, true, &Logic::FairyAccess, RHT_BOTTLE_WITH_FAIRY, ITEM_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50);
itemTable[RG_BUY_ARROWS_10] = Item(RG_BUY_ARROWS_10, Text{ "Buy Arrows (10)", "Acheter: Flèches (10)", "Pfeile kaufen (10)" }, ITEMTYPE_SHOP, GI_ARROWS_SMALL, true, &Logic::BuyArrow, RHT_ARROWS_10, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 20);
itemTable[RG_BUY_BOMBS_20] = Item(RG_BUY_BOMBS_20, Text{ "Buy Bombs (20)", "Acheter: Bombes (20)", "Bomben kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBS_20, true, &Logic::BuyBomb, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 80);
itemTable[RG_BUY_BOMBS_30] = Item(RG_BUY_BOMBS_30, Text{ "Buy Bombs (30)", "Acheter: Bombes (30)", "Bomben kaufen (30)" }, ITEMTYPE_SHOP, GI_BOMBS_30, true, &Logic::BuyBomb, RHT_BOMBS_20, ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 120);
itemTable[RG_BUY_BOMBS_535] = Item(RG_BUY_BOMBS_535, Text{ "Buy Bombs (5) [35]", "Acheter: Bombes (5) [35]", "Bomben kaufen (5) [35]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, &Logic::BuyBomb, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 35);
itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, &Logic::noVariable, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 40);
itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, &Logic::noVariable, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50);
// Misc.
itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, &Logic::noVariable, RHT_NONE);
itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, &Logic::noVariable, RHT_NONE);
// Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen)
itemTable[RG_HOOKSHOT] = Item(RG_HOOKSHOT, Text{ "Hookshot", "Grappin", "Fanghaken" }, ITEMTYPE_ITEM, GI_HOOKSHOT, true, &Logic::ProgressiveHookshot, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_LONGSHOT] = Item(RG_LONGSHOT, Text{ "Longshot", "Super-Grappin", "Enterhaken" }, ITEMTYPE_ITEM, GI_LONGSHOT, true, &Logic::ProgressiveHookshot, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_FAIRY_OCARINA] = Item(RG_FAIRY_OCARINA, Text{ "Fairy Ocarina", "Ocarina des fées", "Feen-Okarina" }, ITEMTYPE_ITEM, GI_OCARINA_FAIRY, true, &Logic::ProgressiveOcarina, RHT_FAIRY_OCARINA, ITEM_OCARINA_FAIRY, OBJECT_GI_OCARINA_0, GID_OCARINA_FAIRY, 0x4A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_OCARINA_OF_TIME] = Item(RG_OCARINA_OF_TIME, Text{ "Ocarina of Time", "Ocarina du Temps", "Okarina der Zeit" }, ITEMTYPE_ITEM, GI_OCARINA_OOT, true, &Logic::ProgressiveOcarina, RHT_OCARINA_OF_TIME, ITEM_OCARINA_TIME, OBJECT_GI_OCARINA, GID_OCARINA_TIME, 0x3A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BOMB_BAG] = Item(RG_BOMB_BAG, Text{ "Bomb Bag", "Sac de Bombes", "Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_20, true, &Logic::ProgressiveBombBag, RHT_BOMB_BAG, ITEM_BOMB_BAG_20, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_20, 0x58, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BIG_BOMB_BAG] = Item(RG_BIG_BOMB_BAG, Text{ "Big Bomb Bag", "Grand Sac de Bombes", "Große Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_30, true, &Logic::ProgressiveBombBag, RHT_BIG_BOMB_BAG, ITEM_BOMB_BAG_30, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_30, 0x59, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_BIGGEST_BOMB_BAG] = Item(RG_BIGGEST_BOMB_BAG, Text{ "Biggest Bomb Bag", "Énorme Sac de Bombes", "Größte Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_40, true, &Logic::ProgressiveBombBag, RHT_BIGGEST_BOMB_BAG, ITEM_BOMB_BAG_40, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, 0x5A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_FAIRY_BOW] = Item(RG_FAIRY_BOW, Text{ "Fairy Bow", "Arc des Fées", "Feen-Bogen" }, ITEMTYPE_ITEM, GI_BOW, true, &Logic::ProgressiveBow, RHT_FAIRY_BOW, ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BIG_QUIVER] = Item(RG_BIG_QUIVER, Text{ "Big Quiver", "Grand carquois", "Großer Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_40, true, &Logic::ProgressiveBow, RHT_BIG_QUIVER, ITEM_QUIVER_40, OBJECT_GI_ARROWCASE, GID_QUIVER_40, 0x56, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_BIGGEST_QUIVER] = Item(RG_BIGGEST_QUIVER, Text{ "Biggest Quiver", "Énorme carquois", "Größter Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_50, true, &Logic::ProgressiveBow, RHT_BIGGEST_QUIVER, ITEM_QUIVER_50, OBJECT_GI_ARROWCASE, GID_QUIVER_50, 0x57, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_FAIRY_SLINGSHOT] = Item(RG_FAIRY_SLINGSHOT, Text{ "Fairy Slingshot", "Lance-Pierre des Fées", "Feen-Schleuder" }, ITEMTYPE_ITEM, GI_SLINGSHOT, true, &Logic::ProgressiveBulletBag,RHT_FAIRY_SLINGSHOT, ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_BIG_BULLET_BAG] = Item(RG_BIG_BULLET_BAG, Text{ "Big Deku Seed Bullet Bag", "Grand sac de graines mojo", "Großer Deku-Samenkugelsack" }, ITEMTYPE_ITEM, GI_BULLET_BAG_40, true, &Logic::ProgressiveBulletBag,RHT_BIG_BULLET_BAG, ITEM_BULLET_BAG_40, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_BIGGEST_BULLET_BAG] = Item(RG_BIGGEST_BULLET_BAG, Text{ "Biggest Deku Seed Bullet Bag", "Énorme sac de graines mojo", "Größte Deku-Samenkugelsack" }, ITEMTYPE_ITEM, GI_BULLET_BAG_50, true, &Logic::ProgressiveBulletBag,RHT_BIGGEST_BULLET_BAG, ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_GORONS_BRACELET] = Item(RG_GORONS_BRACELET, Text{ "Goron's Bracelet", "Bracelet Goron", "Goronen-Armband" }, ITEMTYPE_ITEM, GI_BRACELET, true, &Logic::ProgressiveStrength, RHT_GORONS_BRACELET, ITEM_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, 0x79, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_SILVER_GAUNTLETS] = Item(RG_SILVER_GAUNTLETS, Text{ "Silver Gauntlets", "Gantelets d'argent", "Silberne Fehdehandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_SILVER,true, &Logic::ProgressiveStrength, RHT_SILVER_GAUNTLETS, ITEM_GAUNTLETS_SILVER, OBJECT_GI_GLOVES, GID_GAUNTLETS_SILVER,0x5B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_GOLDEN_GAUNTLETS] = Item(RG_GOLDEN_GAUNTLETS, Text{ "Golden Gauntlets", "Gantelets d'or", "Goldene Fehdehandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_GOLD, true, &Logic::ProgressiveStrength, RHT_GOLDEN_GAUNTLETS, ITEM_GAUNTLETS_GOLD, OBJECT_GI_GLOVES, GID_GAUNTLETS_GOLD, 0x5C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_SILVER_SCALE] = Item(RG_SILVER_SCALE, Text{ "Silver Scale", "Écaille d'argent", "Silberne Skala" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, &Logic::ProgressiveScale, RHT_SILVER_SCALE, ITEM_SCALE_SILVER, OBJECT_GI_SCALE, GID_SCALE_SILVER, 0xCD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_GOLDEN_SCALE] = Item(RG_GOLDEN_SCALE, Text{ "Golden Scale", "Écaille d'or", "Goldene Skala" }, ITEMTYPE_ITEM, GI_SCALE_GOLD, true, &Logic::ProgressiveScale, RHT_GOLDEN_SCALE, ITEM_SCALE_GOLDEN, OBJECT_GI_SCALE, GID_SCALE_GOLDEN, 0xCE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Erwachsene Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, &Logic::ProgressiveWallet, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesige Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, &Logic::ProgressiveWallet, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE);
itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Reiche Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, &Logic::ProgressiveWallet, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_DEKU_NUT_CAPACITY_30] = Item(RG_DEKU_NUT_CAPACITY_30, Text{ "Deku Nut Capacity (30)", "Capacité de noix Mojo (30)", "Deku Nuss Kapazität (30)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, false, &Logic::noVariable, RHT_DEKU_NUT_CAPACITY_30, ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_DEKU_NUT_CAPACITY_40] = Item(RG_DEKU_NUT_CAPACITY_40, Text{ "Deku Nut Capacity (40)", "Capacité de noix Mojo (40)", "Deku Nuss Kapazität (40)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_40, false, &Logic::noVariable, RHT_DEKU_NUT_CAPACITY_40, ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_DEKU_STICK_CAPACITY_20] = Item(RG_DEKU_STICK_CAPACITY_20, Text{ "Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Deku Stick Kapazität (20)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_20,false, &Logic::noVariable, RHT_DEKU_STICK_CAPACITY_20, ITEM_STICK_UPGRADE_20, OBJECT_GI_STICK, GID_STICK, 0x90, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_DEKU_STICK_CAPACITY_30] = Item(RG_DEKU_STICK_CAPACITY_30, Text{ "Deku Stick Capacity (30)", "Capacité de Bâtons Mojo (30)", "Deku Stick Kapazität (30)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30,false, &Logic::noVariable, RHT_DEKU_STICK_CAPACITY_30, ITEM_STICK_UPGRADE_30, OBJECT_GI_STICK, GID_STICK, 0x91, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE);
itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Messgerät" }, ITEMTYPE_ITEM, 0x8A, true, &Logic::ProgressiveMagic, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbesserte Magieanzeige" }, ITEMTYPE_ITEM, 0x8A, true, &Logic::ProgressiveMagic, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce Piece" }, ITEMTYPE_ITEM, 0xDF, true, &Logic::TriforcePieces, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
}
Item& Rando::StaticData::RetrieveItem(const RandomizerGet rgid) {
return itemTable[rgid];
}
Item& Rando::StaticData::ItemFromGIID(const int giid) {
uint32_t index = 0;
while (index < RG_MAX) {
if (itemTable[index].GetItemID() == giid) {
return itemTable[index];
}
index++;
}
// there are vanilla items that don't exist in the item table we're reading from here
// if we made it this far, it means we didn't find an item in the table
// if we don't return anything, the game will crash, so, as a workaround, return greg
return itemTable[RG_GREEN_RUPEE];
}
std::array<Item, RG_MAX>& Rando::StaticData::GetItemTable() {
return itemTable;
}

View File

@@ -0,0 +1,189 @@
#include "item_location.h"
namespace Rando {
ItemLocation::ItemLocation(RandomizerCheck rc_) : rc(rc_) {}
RandomizerCheck ItemLocation::GetRandomizerCheck() const {
return rc;
}
bool ItemLocation::IsAddedToPool() const {
return addedToPool;
}
void ItemLocation::AddToPool() {
addedToPool = true;
}
void ItemLocation::RemoveFromPool() {
addedToPool = false;
}
const Item& ItemLocation::GetPlacedItem() const {
return Rando::StaticData::RetrieveItem(placedItem);
}
const Text& ItemLocation::GetPlacedItemName() const {
return Rando::StaticData::RetrieveItem(placedItem).GetName();
}
RandomizerGet ItemLocation::GetPlacedRandomizerGet() const {
return placedItem;
}
void ItemLocation::SetPlacedItem(const RandomizerGet item) {
placedItem = item;
SetPrice (StaticData::RetrieveItem(placedItem).GetPrice());
}
void ItemLocation::SetDelayedItem(const RandomizerGet item) {
delayedItem = item;
}
void ItemLocation::SaveDelayedItem () {
placedItem = delayedItem;
delayedItem = RG_NONE;
}
void ItemLocation::SetParentRegion(RandomizerRegion region) {
parentRegion = region;
}
RandomizerRegion ItemLocation::GetParentRegionKey() const {
return parentRegion;
}
void ItemLocation::PlaceVanillaItem() {
placedItem = Rando::StaticData::GetLocation(rc)->GetVanillaItem();
}
void ItemLocation::ApplyPlacedItemEffect() {
Rando::StaticData::RetrieveItem(placedItem).ApplyEffect();
}
uint16_t ItemLocation::GetPrice() const {
if (StaticData::RetrieveItem(placedItem).GetItemType() == ITEMTYPE_SHOP) {
return Rando::StaticData::RetrieveItem(placedItem).GetPrice();
}
return price;
}
void ItemLocation::SetPrice(uint16_t price_) {
if (hasShopsanityPrice || hasScrubsanityPrice) {
return;
}
price = price_;
}
bool ItemLocation::HasShopsanityPrice() const {
return hasShopsanityPrice;
}
void ItemLocation::SetShopsanityPrice(uint16_t price_) {
price = price_;
hasShopsanityPrice = true;
}
bool ItemLocation::HasScrubsanityPrice() const {
return hasScrubsanityPrice;
}
void ItemLocation::SetScrubsanityPrice(uint16_t price_) {
price = price_;
hasScrubsanityPrice = true;
}
bool ItemLocation::IsHintable() const {
return isHintable;
}
void ItemLocation::SetAsHintable() {
isHintable = true;
}
bool ItemLocation::IsHintedAt() const {
return hintedAt;
}
void ItemLocation::SetAsHinted() {
hintedAt = true;
}
RandomizerHintKey ItemLocation::GetHintKey() const {
return hintedBy;
}
void ItemLocation::SetHintKey(RandomizerHintKey hintKey) {
hintedBy = hintKey;
}
bool ItemLocation::IsHidden() const {
return hidden;
}
void ItemLocation::SetHidden(const bool hidden_) {
hidden = hidden_;
}
bool ItemLocation::IsExcluded() const {
return excludedOption.Value<bool>();
}
Option* ItemLocation::GetExcludedOption() {
return &excludedOption;
}
void ItemLocation::AddExcludeOption() {
const std::string name = StaticData::GetLocation(rc)->GetName();
if (name.length() < 23) {
excludedOption = Option::Bool(name, {"Include", "Exclude"});
} else {
size_t lastSpace = name.rfind(' ', 23);
std::string settingText = name;
settingText.replace(lastSpace, 1, "\n ");
excludedOption = Option::Bool(settingText, {"Include", "Exclude"});
}
// RANDOTODO: this without string compares and loops
bool alreadyAdded = false;
Rando::Location* loc = StaticData::GetLocation(rc);
for (const Option* location : Settings::excludeLocationsOptionsVector[loc->GetCollectionCheckGroup()]) {
if (location->GetName() == excludedOption.GetName()) {
alreadyAdded = true;
}
}
if (!alreadyAdded) {
Settings::excludeLocationsOptionsVector[loc->GetCollectionCheckGroup()].push_back(&excludedOption);
}
}
bool ItemLocation::IsVisible() const {
return visibleInImGui;
}
void ItemLocation::SetVisible(bool visibleInImGui_) {
visibleInImGui = visibleInImGui_;
}
ItemOverride_Key ItemLocation::Key() const {
ItemOverride_Key key;
key.all = 0;
key.scene = Rando::StaticData::GetLocation(rc)->GetScene();
key.type = static_cast<uint8_t>(StaticData::GetLocation(rc)->GetLocationType()); // TODO make sure these match up
return key;
}
void ItemLocation::ResetVariables() {
addedToPool = false;
placedItem = RG_NONE;
delayedItem = RG_NONE;
isHintable = false;
hintedAt = false;
hintedBy = RH_NONE;
price = 0;
hasShopsanityPrice = false;
hasScrubsanityPrice = false;
hidden = false;
}
}

View File

@@ -0,0 +1,105 @@
#pragma once
#include "randomizerTypes.h"
#include "item.h"
#include "3drando/text.hpp"
#include "static_data.h"
namespace Rando {
enum ItemOverride_Type {
OVR_BASE_ITEM = 0,
OVR_CHEST = 1,
OVR_COLLECTABLE = 2,
OVR_SKULL = 3,
OVR_GROTTO_SCRUB = 4,
OVR_DELAYED = 5,
OVR_TEMPLE = 6,
};
typedef union ItemOverride_Key {
uint32_t all;
struct {
char pad_;
uint8_t scene;
uint8_t type;
};
} ItemOverride_Key;
typedef union ItemOverride_Value {
uint32_t all;
struct {
uint16_t itemId;
uint8_t player;
uint8_t looksLikeItemId;
};
} ItemOverride_Value;
typedef struct ItemOverride {
ItemOverride_Key key;
ItemOverride_Value value;
} ItemOverride;
class ItemOverride_Compare {
public:
bool operator()(ItemOverride lhs, ItemOverride rhs) const {
return lhs.key.all < rhs.key.all;
}
};
class ItemLocation {
public:
ItemLocation() = default;
ItemLocation(RandomizerCheck rc);
RandomizerCheck GetRandomizerCheck() const;
bool IsAddedToPool() const;
void AddToPool();
void RemoveFromPool();
const Item& GetPlacedItem() const;
const Text& GetPlacedItemName() const;
RandomizerGet GetPlacedRandomizerGet() const;
void SetPlacedItem(const RandomizerGet item);
void SetDelayedItem(const RandomizerGet item);
RandomizerRegion GetParentRegionKey() const;
void SetParentRegion (RandomizerRegion region);
void PlaceVanillaItem();
void ApplyPlacedItemEffect();
void SaveDelayedItem();
uint16_t GetPrice() const;
void SetPrice(uint16_t price_);
bool HasShopsanityPrice() const;
void SetShopsanityPrice(uint16_t price_);
bool HasScrubsanityPrice() const;
void SetScrubsanityPrice(uint16_t price_);
bool IsHintable() const;
void SetAsHintable();
bool IsHintedAt() const;
void SetAsHinted();
RandomizerHintKey GetHintKey() const;
void SetHintKey(RandomizerHintKey hintKey);
bool IsHidden() const;
bool IsExcluded() const;
void AddExcludeOption();
Option* GetExcludedOption();
void SetHidden(const bool hidden_);
bool IsVisible() const;
void SetVisible(bool visibleInImGui_);
Rando::ItemOverride_Key Key() const;
void ResetVariables();
private:
RandomizerCheck rc;
RandomizerHintKey hintedBy;
bool hintedAt = false;
bool isHintable = false;
bool addedToPool = false;
RandomizerGet placedItem = RG_NONE;
RandomizerGet delayedItem = RG_NONE;
Option excludedOption = Option::Bool(StaticData::GetLocation(rc)->GetName(), {"Include", "Exclude"});
uint16_t price = 0;
RandomizerRegion parentRegion = RR_NONE;
bool hasShopsanityPrice = false;
bool hasScrubsanityPrice = false;
bool hidden = false;
bool visibleInImGui = false;
};
} // namespace Rando

View File

@@ -0,0 +1,252 @@
#include "location.h"
#include "3drando/hint_list.hpp"
RandomizerCheck Rando::Location::GetRandomizerCheck() const {
return rc;
}
Rando::SpoilerCollectionCheck Rando::Location::GetCollectionCheck() const {
return collectionCheck;
}
SpoilerCollectionCheckGroup Rando::Location::GetCollectionCheckGroup() const {
return collectionCheckGroup;
}
RandomizerCheckQuest Rando::Location::GetQuest() const {
return quest;
}
RandomizerCheckArea Rando::Location::GetArea() const {
return area;
}
RandomizerCheckType Rando::Location::GetRCType() const {
return checkType;
}
ActorID Rando::Location::GetActorID() const {
return actorId;
}
int32_t Rando::Location::GetActorParams() const {
return actorParams;
}
SceneID Rando::Location::GetScene() const {
return (SceneID)scene;
}
uint8_t Rando::Location::GetFlag() const {
return flag;
}
RandomizerHintTextKey Rando::Location::GetHintKey() const {
return hintKey;
}
HintText* Rando::Location::GetHint() {
return &hintTable[hintKey];
}
const std::string& Rando::Location::GetName() const {
return spoilerName;
}
const std::string& Rando::Location::GetShortName() const {
return shortName;
}
Rando::LocationType Rando::Location::GetLocationType() const {
return locationType;
}
bool Rando::Location::IsCategory(Category category) const {
return std::any_of(categories.begin(), categories.end(), [category](auto entry) { return entry == category; });
}
bool Rando::Location::IsDungeon() const {
return (locationType != LocationType::GSToken &&
(scene < SCENE_GANONS_TOWER_COLLAPSE_INTERIOR ||
(scene > SCENE_TREASURE_BOX_SHOP && scene < SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR))) ||
(locationType == LocationType::GSToken && scene < SCENE_GANONS_TOWER);
}
bool Rando::Location::IsOverworld() const {
return !IsDungeon();
}
bool Rando::Location::IsShop() const {
return (scene >= SCENE_BAZAAR && scene <= SCENE_BOMBCHU_SHOP);
}
bool Rando::Location::IsVanillaCompletion() const {
return isVanillaCompletion;
}
uint32_t Rando::Location::Getuint32_t() const {
return hintKey;
}
const HintText& Rando::Location::GetHint() const {
return Hint(hintKey);
}
RandomizerGet Rando::Location::GetVanillaItem() const {
return vanillaItem;
}
Rando::Location Rando::Location::Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_, int32_t actorParams_,
uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_,
const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem,
std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck,
SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::Base, actorId_, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), hintKey, vanillaItem, std::move(categories),
isVanillaCompletion_, collectionCheck, collectionCheckGroup);
}
Rando::Location Rando::Location::Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_,
int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey,
const RandomizerGet vanillaItem, std::vector<Category>&& categories,
SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::Chest, actorId_, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), hintKey, vanillaItem, std::move(categories),
isVanillaCompletion_,
SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_CHEST, scene_, flag_),
collectionCheckGroup);
}
Rando::Location Rando::Location::Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_,
int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey,
const RandomizerGet vanillaItem, std::vector<Category>&& categories,
SpoilerCollectionCheck collectionCheck,
SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::Chest, actorId_, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), hintKey, vanillaItem, std::move(categories),
isVanillaCompletion_, collectionCheck, collectionCheckGroup);
}
Rando::Location Rando::Location::Collectable(
RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_,
ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem,
std::vector<Category>&& categories, SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::Collectable, actorId_, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), hintKey, vanillaItem, std::move(categories),
isVanillaCompletion_,
SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE, scene_, flag_),
collectionCheckGroup);
}
Rando::Location Rando::Location::Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_,
RandomizerCheckType checkType_, RandomizerCheckArea area_,
ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_,
std::string&& shortName_, std::string&& spoilerName_,
const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem,
std::vector<Category>&& categories, uint8_t collectFlag_,
SpoilerCollectionCheckGroup collectionCheckGroup,
bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::Collectable, actorId_, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), hintKey, vanillaItem, std::move(categories),
isVanillaCompletion_,
SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE, scene_, collectFlag_),
collectionCheckGroup);
}
Rando::Location Rando::Location::Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_,
RandomizerCheckType checkType_, RandomizerCheckArea area_,
ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_,
std::string&& shortName_, std::string&& spoilerName_,
const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem,
std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck,
SpoilerCollectionCheckGroup collectionCheckGroup,
bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::Collectable, actorId_, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), hintKey, vanillaItem, std::move(categories),
isVanillaCompletion_, collectionCheck, collectionCheckGroup);
}
Rando::Location Rando::Location::GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_,
uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey,
std::vector<Category>&& categories,
SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) {
return Location(rc, quest_, RCTYPE_SKULL_TOKEN, area_, LocationType::GSToken, ACTOR_EN_SI, scene_, actorParams_,
flag_, std::move(shortName_), std::move(spoilerName_), hintKey, RG_GOLD_SKULLTULA_TOKEN,
std::move(categories), isVanillaCompletion_,
SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA, scene_, flag_),
collectionCheckGroup);
}
Rando::Location Rando::Location::GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_,
uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey,
std::vector<Category>&& categories, uint8_t skullScene_,
SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) {
return Location(rc, quest_, RCTYPE_SKULL_TOKEN, area_, LocationType::GSToken, ACTOR_EN_SI, scene_, actorParams_,
flag_, std::move(shortName_), std::move(spoilerName_), hintKey, RG_GOLD_SKULLTULA_TOKEN,
std::move(categories), isVanillaCompletion_,
SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA, skullScene_, flag_),
collectionCheckGroup);
}
Rando::Location Rando::Location::GrottoScrub(RandomizerCheck rc, RandomizerCheckQuest quest_,
RandomizerCheckType checkType_, RandomizerCheckArea area_,
ActorID actorId_, uint8_t scene_, int32_t actorParams_, uint8_t flag_,
std::string&& shortName_, std::string&& spoilerName_,
const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem,
std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck,
SpoilerCollectionCheckGroup collectionCheckGroup,
bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::GrottoScrub, actorId_, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), hintKey, vanillaItem, std::move(categories),
isVanillaCompletion_, collectionCheck, collectionCheckGroup);
}
Rando::Location Rando::Location::Delayed(RandomizerCheck rc, RandomizerCheckQuest quest_,
RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_,
uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey,
const RandomizerGet vanillaItem, std::vector<Category>&& categories,
SpoilerCollectionCheck collectionCheck,
SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::Delayed, actorId_, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), hintKey, vanillaItem, std::move(categories),
isVanillaCompletion_, collectionCheck, collectionCheckGroup);
}
Rando::Location Rando::Location::Reward(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene_,
int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey,
const RandomizerGet vanillaItem, std::vector<Category>&& categories,
SpoilerCollectionCheck collectionCheck,
SpoilerCollectionCheckGroup collectionCheckGroup, bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::TempleReward, actorId_, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), hintKey, vanillaItem, std::move(categories),
isVanillaCompletion_, collectionCheck, collectionCheckGroup);
}
Rando::Location Rando::Location::OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_,
RandomizerCheckType checkType_, RandomizerCheckArea area_, ActorID actorId_,
uint8_t scene_, int32_t actorParams_, uint8_t flag_,
std::string&& shortName_, std::string&& spoilerName_,
std::vector<Category>&& categories, bool isVanillaCompletion_) {
return Location(rc, quest_, checkType_, area_, LocationType::OtherHint, actorId_, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), RHT_NONE, RG_NONE, std::move(categories), isVanillaCompletion_);
}
Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_,
uint8_t scene_, int32_t actorParams_, uint8_t flag_,
std::string&& shortName_, std::string&& spoilerName_,
std::vector<Category>&& categories, bool isVanillaCompletion_) {
return Location(rc, quest_, RCTYPE_GOSSIP_STONE, area_, LocationType::Base, ACTOR_EN_GS, scene_, actorParams_, flag_,
std::move(shortName_), std::move(spoilerName_), RHT_NONE, RG_NONE, std::move(categories),
isVanillaCompletion_);
}

View File

@@ -0,0 +1,285 @@
#pragma once
#include <vector>
#include "3drando/spoiler_log.hpp"
#include "3drando/category.hpp"
#include "3drando/hints.hpp"
#include "z64item.h"
#include "randomizerTypes.h"
#include "z64actor_enum.h"
#include "z64scene.h"
namespace Rando {
class SpoilerCollectionCheck {
public:
SpoilerCollectionCheckType type = SpoilerCollectionCheckType::SPOILER_CHK_NONE;
uint8_t scene = 0;
uint8_t flag = 0;
SpoilerCollectionCheck() {
}
SpoilerCollectionCheck(SpoilerCollectionCheckType type_, uint8_t scene_, uint8_t flag_)
: type(type_), scene(scene_), flag(flag_) {
}
static auto None() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_NONE, 0x00, 0x00);
}
static auto AlwaysCollected() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_ALWAYS_COLLECTED, 0x00, 0x00);
}
static auto ItemGetInf(uint8_t slot) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF, 0x00, slot);
}
static auto EventChkInf(uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF, 0xFF, flag);
}
static auto InfTable(uint8_t offset, uint8_t bit) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_INF_TABLE, offset, bit);
}
static auto Collectable(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE, scene, flag);
}
static auto Chest(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_CHEST, scene, flag);
}
static auto Cow(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COW, scene, flag);
}
static auto Fishing(uint8_t bit) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MINIGAME, 0x00, bit);
}
static auto Scrub(uint8_t scene, uint8_t bit) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_SCRUB, scene, bit);
}
static auto GerudoToken() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GERUDO_MEMBERSHIP_CARD, 0x00, 0x00);
}
static auto BigPoePoints() {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_POE_POINTS, 0x00, 0x00);
}
static auto Gravedigger(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GRAVEDIGGER, scene, flag);
}
static auto ShopItem(uint8_t scene, uint8_t itemSlot) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM, scene, itemSlot);
}
static auto MagicBeans(uint8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MAGIC_BEANS, scene, flag);
}
static auto Merchant(int8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT, scene, flag);
}
static auto RandomizerInf(int8_t scene, uint8_t flag) {
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF, scene, flag);
}
};
enum class LocationType {
Base,
Chest,
Collectable,
GSToken,
GrottoScrub,
Delayed,
TempleReward,
HintStone,
OtherHint,
};
class Location {
public:
Location() = default;
Location(RandomizerCheck rc_, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, LocationType locationType_, ActorID actorId_, uint8_t scene_,
int32_t actorParams_, uint8_t flag_, std::string shortName_, std::string spoilerName_,
RandomizerHintTextKey hintKey_, RandomizerGet vanillaItem_, std::vector<Category> categories_,
bool isVanillaCompletion_ = false, SpoilerCollectionCheck collectionCheck_ = SpoilerCollectionCheck(),
SpoilerCollectionCheckGroup collectionCheckGroup_ = SpoilerCollectionCheckGroup::GROUP_NO_GROUP)
: rc(rc_), quest(quest_), checkType(checkType_), area(area_), locationType(locationType_), actorId(actorId_),
scene(scene_), actorParams(actorParams_), flag(flag_), shortName(std::move(shortName_)),
spoilerName(spoilerName_), hintKey(hintKey_), vanillaItem(vanillaItem_), categories(std::move(categories_)),
isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_),
collectionCheckGroup(collectionCheckGroup_) {
}
RandomizerCheck GetRandomizerCheck() const;
SpoilerCollectionCheck GetCollectionCheck() const;
SpoilerCollectionCheckGroup GetCollectionCheckGroup() const;
RandomizerCheckQuest GetQuest() const;
RandomizerCheckArea GetArea() const;
RandomizerCheckType GetRCType() const;
ActorID GetActorID() const;
int32_t GetActorParams() const;
SceneID GetScene() const;
uint8_t GetFlag() const;
RandomizerHintTextKey GetHintKey() const;
HintText* GetHint();
const std::string& GetName() const;
const std::string& GetShortName() const;
LocationType GetLocationType() const;
bool IsCategory(Category category) const;
bool IsDungeon() const;
bool IsOverworld() const;
bool IsShop() const;
bool IsVanillaCompletion() const;
uint32_t Getuint32_t() const;
const HintText& GetHint() const;
RandomizerGet GetVanillaItem() const;
static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene, int32_t actorParams_,
uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_,
const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem,
std::vector<Category>&& categories,
SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP,
bool isVanillaCompletion_ = false);
static Location
Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_,
ActorID actorId_, uint8_t scene, int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem,
std::vector<Category>&& categories,
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP,
bool isVanillaCompletion_ = false);
static Location
Chest(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_,
ActorID actorId_, uint8_t scene, int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem,
std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP,
bool isVanillaCompletion_ = false);
static Location
Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene, int32_t actorParams_, uint8_t flag_,
std::string&& shortName_, std::string&& spoilerName_, const RandomizerHintTextKey hintKey,
const RandomizerGet vanillaItem, std::vector<Category>&& categories,
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP,
bool isVanillaCompletion_ = false);
static Location
Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene, int32_t actorParams_, uint8_t flag_,
std::string&& shortName_, std::string&& spoilerName_, const RandomizerHintTextKey hintKey,
const RandomizerGet vanillaItem, std::vector<Category>&& categories, uint8_t collectFlag_,
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP,
bool isVanillaCompletion_ = false);
static Location
Collectable(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene, int32_t actorParams_, uint8_t flag_,
std::string&& shortName_, std::string&& spoilerName_, const RandomizerHintTextKey hintKey,
const RandomizerGet vanillaItem, std::vector<Category>&& categories,
SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP,
bool isVanillaCompletion_ = false);
static Location
GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_,
uint8_t scene, int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey, std::vector<Category>&& categories,
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP,
bool isVanillaCompletion_ = true);
/// @brief For certain scenes, the sceneId and the "Scene" in spoiler collection check later used to check the
/// GS flags don't necessarily match. Use this constructor for those. scene_ should be the actual scene where
/// the GS is located, skullScene_ is the value passed to GET_GS_FLAGS to get the correct skulltula. It is normal
/// and expected that these don't always match, and the naming is a holdover from 3drando.
/// @param rc
/// @param quest_
/// @param area_
/// @param scene_
/// @param actorParams_
/// @param flag_
/// @param shortName_
/// @param spoilerName_
/// @param hintKey
/// @param categories
/// @param collectionCheckGroup
/// @param skullScene_
/// @param isVanillaCompletion_
/// @return
static Location
GSToken(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_,
uint8_t scene_, int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey, std::vector<Category>&& categories,
uint8_t skullScene_,
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP,
bool isVanillaCompletion_ = true);
static Location
GrottoScrub(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene, int32_t actorParams_, uint8_t flag_,
std::string&& shortName_, std::string&& spoilerName_, const RandomizerHintTextKey hintKey,
const RandomizerGet vanillaItem, std::vector<Category>&& categories,
SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP,
bool isVanillaCompletion_ = false);
static Location
Delayed(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_,
ActorID actorId_, uint8_t scene, int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem,
std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP,
bool isVanillaCompletion_ = false);
static Location
Reward(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, RandomizerCheckArea area_,
ActorID actorId_, uint8_t scene, int32_t actorParams_, uint8_t flag_, std::string&& shortName_,
std::string&& spoilerName_, const RandomizerHintTextKey hintKey, const RandomizerGet vanillaItem,
std::vector<Category>&& categories, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
SpoilerCollectionCheckGroup collectionCheckGroup = SpoilerCollectionCheckGroup::GROUP_NO_GROUP, bool isVanillaCompletion_ = false);
static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
RandomizerCheckArea area_, ActorID actorId_, uint8_t scene, int32_t actorParams_,
uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_,
std::vector<Category>&& categories, bool isVanillaCompletion_ = false);
static Location HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, uint8_t scene,
int32_t actorParams_, uint8_t flag_, std::string&& shortName_, std::string&& spoilerName_,
std::vector<Category>&& categories, bool isVanillaCompletion_ = false);
private:
RandomizerCheck rc;
RandomizerCheckQuest quest;
RandomizerCheckType checkType;
RandomizerCheckArea area;
LocationType locationType;
ActorID actorId;
uint8_t scene;
int32_t actorParams;
uint8_t flag;
bool checked = false;
std::string shortName;
std::string spoilerName;
RandomizerHintTextKey hintKey = RHT_NONE;
RandomizerGet vanillaItem = RG_NONE;
std::vector<Category> categories;
bool isVanillaCompletion = false;
SpoilerCollectionCheck collectionCheck;
SpoilerCollectionCheckGroup collectionCheckGroup;
bool isHintable = false;
};
} // namespace Rando

File diff suppressed because it is too large Load Diff

View File

@@ -26,6 +26,7 @@
#include <functional>
#include "draw.h"
#include "rando_hash.h"
#include "static_data.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include <boost_custom/container_hash/hash_32.hpp>
#include "randomizer_settings_window.h"
@@ -44,7 +45,7 @@ std::unordered_map<std::string, RandomizerCheck> SpoilerfileCheckNameToEnum;
std::unordered_map<std::string, RandomizerGet> SpoilerfileGetNameToEnum;
std::unordered_map<std::string, RandomizerCheckArea> SpoilerfileAreaNameToEnum;
std::unordered_map<std::string, HintType> SpoilerfileHintTypeNameToEnum;
std::multimap<std::tuple<s16, s16, s32>, RandomizerCheckObject> checkFromActorMultimap;
std::multimap<std::tuple<s16, s16, s32>, RandomizerCheck> checkFromActorMultimap;
std::set<RandomizerCheck> excludedLocations;
std::set<RandomizerTrick> enabledTricks;
std::set<RandomizerTrick> enabledGlitches;
@@ -118,14 +119,16 @@ static const char* frenchRupeeNames[36] = {
};
Randomizer::Randomizer() {
for (auto& [randomizerCheck, rcObject] : RandomizerCheckObjects::GetAllRCObjects()) {
SpoilerfileCheckNameToEnum[rcObject.rcSpoilerName] = rcObject.rc;
checkFromActorMultimap.emplace(std::make_tuple((s16)rcObject.actorId, (s16)rcObject.sceneId, rcObject.actorParams), rcObject);
Rando::StaticData::InitItemTable();
Rando::StaticData::InitLocationTable();
for (auto& location : Rando::StaticData::GetLocationTable()) {
SpoilerfileCheckNameToEnum[location.GetName()] = location.GetRandomizerCheck();
checkFromActorMultimap.emplace(std::make_tuple((s16)location.GetActorID(), (s16)location.GetScene(), location.GetActorParams()), location.GetRandomizerCheck());
}
SpoilerfileCheckNameToEnum["Invalid Location"] = RC_UNKNOWN_CHECK;
SpoilerfileCheckNameToEnum["Link's Pocket"] = RC_LINKS_POCKET;
for (auto& item: *RandoMain::GetFullItemTable()) {
for (auto& item: Rando::StaticData::GetItemTable()) {
// Easiest way to filter out all the empty values from the array, since we still technically want the 0/RG_NONE entry
if (item.GetName().english.empty()) continue;
SpoilerfileGetNameToEnum[item.GetName().english] = item.GetRandomizerGet();
@@ -2582,7 +2585,7 @@ std::map<RandomizerCheck, RandomizerInf> rcToRandomizerInf = {
{ RC_MARKET_10_BIG_POES, RAND_INF_10_BIG_POES },
};
RandomizerCheckObject Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams = 0x00) {
Rando::Location* Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams = 0x00) {
RandomizerCheck specialRc = RC_UNKNOWN_CHECK;
// TODO: Migrate these special cases into table, or at least document why they are special
switch(sceneNum) {
@@ -2683,22 +2686,22 @@ RandomizerCheckObject Randomizer::GetCheckObjectFromActor(s16 actorId, s16 scene
}
if (specialRc != RC_UNKNOWN_CHECK) {
return RandomizerCheckObjects::GetAllRCObjects()[specialRc];
return Rando::StaticData::GetLocation(specialRc);
}
auto range = checkFromActorMultimap.equal_range(std::make_tuple(actorId, sceneNum, actorParams));
for (auto it = range.first; it != range.second; ++it) {
if (
it->second.vOrMQ == RCVORMQ_BOTH ||
(it->second.vOrMQ == RCVORMQ_VANILLA && !ResourceMgr_IsGameMasterQuest()) ||
(it->second.vOrMQ == RCVORMQ_MQ && ResourceMgr_IsGameMasterQuest())
Rando::StaticData::GetLocation(it->second)->GetQuest() == RCQUEST_BOTH ||
(Rando::StaticData::GetLocation(it->second)->GetQuest() == RCQUEST_VANILLA && !ResourceMgr_IsGameMasterQuest()) ||
(Rando::StaticData::GetLocation(it->second)->GetQuest() == RCQUEST_MQ && ResourceMgr_IsGameMasterQuest())
) {
return it->second;
return Rando::StaticData::GetLocation(it->second);
}
}
return RandomizerCheckObjects::GetAllRCObjects()[RC_UNKNOWN_CHECK];
return Rando::StaticData::GetLocation(RC_UNKNOWN_CHECK);
}
ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData) {
@@ -2717,15 +2720,15 @@ ScrubIdentity Randomizer::IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respa
actorParams = TWO_ACTOR_PARAMS(actorParams, respawnData);
}
RandomizerCheckObject rcObject = GetCheckObjectFromActor(ACTOR_EN_DNS, sceneNum, actorParams);
Rando::Location* location = GetCheckObjectFromActor(ACTOR_EN_DNS, sceneNum, actorParams);
if (rcObject.rc != RC_UNKNOWN_CHECK) {
scrubIdentity.randomizerInf = rcToRandomizerInf[rcObject.rc];
scrubIdentity.randomizerCheck = rcObject.rc;
scrubIdentity.getItemId = rcObject.ogItemId;
if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) {
scrubIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()];
scrubIdentity.randomizerCheck = location->GetRandomizerCheck();
scrubIdentity.getItemId = (GetItemID)Rando::StaticData::RetrieveItem(location->GetVanillaItem()).GetItemID();
scrubIdentity.isShuffled = GetRandoSettingValue(RSK_SHUFFLE_SCRUBS) != RO_SCRUBS_OFF;
if (rcObject.rc == RC_HF_DEKU_SCRUB_GROTTO || rcObject.rc == RC_LW_DEKU_SCRUB_GROTTO_FRONT || rcObject.rc == RC_LW_DEKU_SCRUB_NEAR_BRIDGE) {
if (location->GetRandomizerCheck() == RC_HF_DEKU_SCRUB_GROTTO || location->GetRandomizerCheck() == RC_LW_DEKU_SCRUB_GROTTO_FRONT || location->GetRandomizerCheck() == RC_LW_DEKU_SCRUB_NEAR_BRIDGE) {
scrubIdentity.isShuffled = true;
}
@@ -2746,14 +2749,14 @@ ShopItemIdentity Randomizer::IdentifyShopItem(s32 sceneNum, u8 slotIndex) {
shopItemIdentity.itemPrice = -1;
shopItemIdentity.enGirlAShopItem = 0x32;
RandomizerCheckObject rcObject = GetCheckObjectFromActor(ACTOR_EN_GIRLA,
Rando::Location* location = GetCheckObjectFromActor(ACTOR_EN_GIRLA,
// Bazaar (SHOP1) scene is reused, so if entering from Kak use debug scene to identify
(sceneNum == SCENE_BAZAAR && gSaveContext.entranceIndex == 0xB7) ? SCENE_TEST01 : sceneNum, slotIndex);
if (rcObject.rc != RC_UNKNOWN_CHECK) {
shopItemIdentity.randomizerInf = rcToRandomizerInf[rcObject.rc];
shopItemIdentity.randomizerCheck = rcObject.rc;
shopItemIdentity.ogItemId = rcObject.ogItemId;
if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) {
shopItemIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()];
shopItemIdentity.randomizerCheck = location->GetRandomizerCheck();
shopItemIdentity.ogItemId = (GetItemID)Rando::StaticData::RetrieveItem(location->GetVanillaItem()).GetItemID();
RandomizerGetData randoGet = GetRandomizerGetDataFromKnownCheck(shopItemIdentity.randomizerCheck);
if (randomizerGetToEnGirlShopItem.find(randoGet.rgID) != randomizerGetToEnGirlShopItem.end()) {
@@ -2780,11 +2783,11 @@ CowIdentity Randomizer::IdentifyCow(s32 sceneNum, s32 posX, s32 posZ) {
actorParams = TWO_ACTOR_PARAMS(posX, posZ);
}
RandomizerCheckObject rcObject = GetCheckObjectFromActor(ACTOR_EN_COW, sceneNum, actorParams);
Rando::Location* location = GetCheckObjectFromActor(ACTOR_EN_COW, sceneNum, actorParams);
if (rcObject.rc != RC_UNKNOWN_CHECK) {
cowIdentity.randomizerInf = rcToRandomizerInf[rcObject.rc];
cowIdentity.randomizerCheck = rcObject.rc;
if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) {
cowIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()];
cowIdentity.randomizerCheck = location->GetRandomizerCheck();
}
return cowIdentity;
@@ -2802,27 +2805,17 @@ GetItemEntry Randomizer::GetItemEntryFromRGData(RandomizerGetData rgData, GetIte
if (checkObtainability && OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerGet(rgData.rgID) != CAN_OBTAIN) {
return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, GI_RUPEE_BLUE);
}
// Can't get RG_ICE_TRAP if the rgID corresponds to a vanilla item
if (IsItemVanilla(rgData.rgID)) {
return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, GetItemIdFromRandomizerGet(rgData.rgID, ogItemId));
}
// After this point we can assume we are dealing with a randomizer exclusive item.
GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(
MOD_RANDOMIZER, GetItemIdFromRandomizerGet(rgData.rgID, ogItemId));
// If we have an ice trap, we want to change the GID and DrawFunc to the fakeRgID's values.
Rando::Item item = Rando::StaticData::RetrieveItem(rgData.rgID);
GetItemEntry giEntry = item.GetGIEntry_Copy();
// If we have an ice trap, we want to change the GID and drawFunc to the fakeRgID's values.
if (rgData.rgID == RG_ICE_TRAP) {
ModIndex modIndex;
if (IsItemVanilla(rgData.fakeRgID)) {
modIndex = MOD_NONE;
} else {
modIndex = MOD_RANDOMIZER;
}
GetItemEntry fakeGiEntry = ItemTableManager::Instance->RetrieveItemEntry(modIndex, GetItemIdFromRandomizerGet(rgData.fakeRgID, ogItemId));
giEntry.gid = fakeGiEntry.gid;
giEntry.gi = fakeGiEntry.gi;
giEntry.drawItemId = fakeGiEntry.drawItemId;
giEntry.drawModIndex = fakeGiEntry.drawModIndex;
giEntry.drawFunc = fakeGiEntry.drawFunc;
std::shared_ptr<GetItemEntry> fakeGiEntry = Rando::StaticData::RetrieveItem(rgData.fakeRgID).GetGIEntry();
giEntry.gid = fakeGiEntry->gid;
giEntry.gi = fakeGiEntry->gi;
giEntry.drawItemId = fakeGiEntry->drawItemId;
giEntry.drawModIndex = fakeGiEntry->drawModIndex;
giEntry.drawFunc = fakeGiEntry->drawFunc;
}
return giEntry;
}
@@ -2833,7 +2826,7 @@ GetItemEntry Randomizer::GetItemFromKnownCheck(RandomizerCheck randomizerCheck,
}
RandomizerCheck Randomizer::GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams) {
return GetCheckObjectFromActor(actorId, sceneNum, actorParams).rc;
return GetCheckObjectFromActor(actorId, sceneNum, actorParams)->GetRandomizerCheck();
}
RandomizerInf Randomizer::GetRandomizerInfFromCheck(RandomizerCheck rc) {
@@ -3070,9 +3063,10 @@ void GenerateRandomizerImgui(std::string seed = "") {
RandomizerCheckObjects::UpdateImGuiVisibility();
// Remove excludes for locations that are no longer allowed to be excluded
for (auto& [randomizerCheck, rcObject] : RandomizerCheckObjects::GetAllRCObjects()) {
auto elfound = excludedLocations.find(rcObject.rc);
if (!rcObject.visibleInImgui && elfound != excludedLocations.end()) {
auto ctx = Rando::Context::GetInstance();
for (auto& location : Rando::StaticData::GetLocationTable()) {
auto elfound = excludedLocations.find(location.GetRandomizerCheck());
if (!ctx->GetItemLocation(location.GetRandomizerCheck())->IsVisible() && elfound != excludedLocations.end()) {
excludedLocations.erase(elfound);
}
}
@@ -3095,6 +3089,7 @@ bool GenerateRandomizer(std::string seed /*= ""*/) {
}
void RandomizerSettingsWindow::DrawElement() {
auto ctx = Rando::Context::GetInstance();
if (generated) {
generated = 0;
randoThread.join();
@@ -4652,11 +4647,11 @@ void RandomizerSettingsWindow::DrawElement() {
locationSearch.Draw();
ImGui::BeginChild("ChildIncludedLocations", ImVec2(0, -8));
for (auto& [rcArea, rcObjects] : RandomizerCheckObjects::GetAllRCObjectsByArea()) {
for (auto& [rcArea, locations] : RandomizerCheckObjects::GetAllRCObjectsByArea()) {
bool hasItems = false;
for (auto& [randomizerCheck, rcObject] : rcObjects) {
if (rcObject->visibleInImgui && !excludedLocations.count(rcObject->rc) &&
locationSearch.PassFilter(rcObject->rcSpoilerName.c_str())) {
for (RandomizerCheck rc : locations) {
if (ctx->GetItemLocation(rc)->IsVisible() && !excludedLocations.count(rc) &&
locationSearch.PassFilter(Rando::StaticData::GetLocation(rc)->GetName().c_str())) {
hasItems = true;
break;
@@ -4666,12 +4661,12 @@ void RandomizerSettingsWindow::DrawElement() {
if (hasItems) {
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode(RandomizerCheckObjects::GetRCAreaName(rcArea).c_str())) {
for (auto& [randomizerCheck, rcObject] : rcObjects) {
if (rcObject->visibleInImgui && !excludedLocations.count(rcObject->rc) &&
locationSearch.PassFilter(rcObject->rcSpoilerName.c_str())) {
for (auto& location : locations) {
if (ctx->GetItemLocation(location)->IsVisible() && !excludedLocations.count(location) &&
locationSearch.PassFilter(Rando::StaticData::GetLocation(location)->GetName().c_str())) {
if (ImGui::ArrowButton(std::to_string(rcObject->rc).c_str(), ImGuiDir_Right)) {
excludedLocations.insert(rcObject->rc);
if (ImGui::ArrowButton(std::to_string(location).c_str(), ImGuiDir_Right)) {
excludedLocations.insert(location);
// todo: this efficently when we build out cvar array support
std::string excludedLocationString = "";
for (auto excludedLocationIt : excludedLocations) {
@@ -4682,7 +4677,7 @@ void RandomizerSettingsWindow::DrawElement() {
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
ImGui::SameLine();
ImGui::Text("%s", rcObject->rcShortName.c_str());
ImGui::Text("%s", Rando::StaticData::GetLocation(location)->GetShortName().c_str());
}
}
ImGui::TreePop();
@@ -4696,10 +4691,10 @@ void RandomizerSettingsWindow::DrawElement() {
window->DC.CurrLineTextBaseOffset = 0.0f;
ImGui::BeginChild("ChildExcludedLocations", ImVec2(0, -8));
for (auto& [rcArea, rcObjects] : RandomizerCheckObjects::GetAllRCObjectsByArea()) {
for (auto& [rcArea, locations] : RandomizerCheckObjects::GetAllRCObjectsByArea()) {
bool hasItems = false;
for (auto& [randomizerCheck, rcObject] : rcObjects) {
if (rcObject->visibleInImgui && excludedLocations.count(rcObject->rc)) {
for (RandomizerCheck rc : locations) {
if (ctx->GetItemLocation(rc)->IsVisible() && excludedLocations.count(rc)) {
hasItems = true;
break;
}
@@ -4708,10 +4703,10 @@ void RandomizerSettingsWindow::DrawElement() {
if (hasItems) {
ImGui::SetNextItemOpen(true, ImGuiCond_Once);
if (ImGui::TreeNode(RandomizerCheckObjects::GetRCAreaName(rcArea).c_str())) {
for (auto& [randomizerCheck, rcObject] : rcObjects) {
auto elfound = excludedLocations.find(rcObject->rc);
if (rcObject->visibleInImgui && elfound != excludedLocations.end()) {
if (ImGui::ArrowButton(std::to_string(rcObject->rc).c_str(), ImGuiDir_Left)) {
for (auto& location : locations) {
auto elfound = excludedLocations.find(location);
if (ctx->GetItemLocation(location)->IsVisible() && elfound != excludedLocations.end()) {
if (ImGui::ArrowButton(std::to_string(location).c_str(), ImGuiDir_Left)) {
excludedLocations.erase(elfound);
// todo: this efficently when we build out cvar array support
std::string excludedLocationString = "";
@@ -4723,7 +4718,7 @@ void RandomizerSettingsWindow::DrawElement() {
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
ImGui::SameLine();
ImGui::Text("%s", rcObject->rcShortName.c_str());
ImGui::Text("%s", Rando::StaticData::GetLocation(location)->GetShortName().c_str());
}
}
ImGui::TreePop();
@@ -6278,5 +6273,4 @@ void InitRandoItemTable() {
void RandomizerSettingsWindow::InitElement() {
Randomizer::CreateCustomMessages();
seedString = (char*)calloc(MAX_SEED_STRING_SIZE, sizeof(char));
InitRandoItemTable();
}

View File

@@ -7,6 +7,7 @@
#include <libultraship/libultra.h>
#include "z64item.h"
#include <memory>
#include "context.h"
#include <soh/Enhancements/randomizer/randomizerTypes.h>
#include "soh/Enhancements/randomizer/randomizer_check_objects.h"
#include "soh/Enhancements/randomizer/randomizer_tricks.h"
@@ -85,7 +86,7 @@ class Randomizer {
std::string GetDampeText() const;
std::string GetSheikText() const;
std::string GetSariaText() const;
RandomizerCheckObject GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams);
Rando::Location* GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams);
ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData);
ShopItemIdentity IdentifyShopItem(s32 sceneNum, u8 slotIndex);
CowIdentity IdentifyCow(s32 sceneNum, s32 posX, s32 posZ);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +1,18 @@
#pragma once
#include "randomizerTypes.h"
#include "z64actor_enum.h"
#include "z64scene.h"
#include <string>
#include <vector>
#include <map>
// Forward Declarations to avoid duplicate definition issues
enum ActorID : int;
enum SceneID : int;
#define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b)
#define RC_OBJECT(rc, rc_v_or_mq, rc_type, rc_area, actor_id, scene_id, actor_params, og_item_id, rc_shortname, rc_spoilername, vanillaCompletion) \
{ rc, {rc, rc_v_or_mq, rc_type, rc_area, actor_id, scene_id, actor_params, og_item_id, false, rc_shortname, rc_spoilername, vanillaCompletion} }
typedef struct {
RandomizerCheck rc;
RandomizerCheckVanillaOrMQ vOrMQ;
RandomizerCheckType rcType;
RandomizerCheckArea rcArea;
ActorID actorId;
SceneID sceneId;
int32_t actorParams;
GetItemID ogItemId;
bool visibleInImgui;
std::string rcShortName;
std::string rcSpoilerName;
bool vanillaCompletion;
} RandomizerCheckObject;
namespace RandomizerCheckObjects {
bool AreaIsDungeon(RandomizerCheckArea area);
bool AreaIsOverworld(RandomizerCheckArea area);
std::string GetRCAreaName(RandomizerCheckArea area);
std::map<RandomizerCheck, RandomizerCheckObject> GetAllRCObjects();
std::map<RandomizerCheckArea, std::map<RandomizerCheck, RandomizerCheckObject*>> GetAllRCObjectsByArea();
std::map<RandomizerCheckArea, std::vector<RandomizerCheck>> GetAllRCObjectsByArea();
std::map<SceneID, RandomizerCheckArea> GetAllRCAreaBySceneID();
RandomizerCheckArea GetRCAreaBySceneID(SceneID sceneId);
void UpdateImGuiVisibility();

View File

@@ -9,9 +9,11 @@
#include <vector>
#include <set>
#include <libultraship/libultraship.h>
#include "3drando/item_location.hpp"
#include "location.h"
#include "item_location.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "z64item.h"
#include "randomizerTypes.h"
extern "C" {
#include "variables.h"
@@ -78,6 +80,7 @@ bool initialized;
bool doAreaScroll;
bool previousShowHidden = false;
bool hideShopRightChecks = true;
bool hideTriforceCompleted = true;
bool checkCollected = false;
int checkLoops = 0;
@@ -110,7 +113,7 @@ std::map<SceneID, RandomizerCheckArea> RCAreaFromSceneID = {
{SCENE_INSIDE_GANONS_CASTLE, RCAREA_GANONS_CASTLE},
};
std::map<RandomizerCheckArea, std::vector<RandomizerCheckObject>> checksByArea;
std::map<RandomizerCheckArea, std::vector<RandomizerCheck>> checksByArea;
bool areasFullyChecked[RCAREA_INVALID];
u32 areasSpoiled = 0;
bool showVOrMQ;
@@ -126,9 +129,9 @@ std::vector<GetItemEntry> itemsReceived;
OSContPad* trackerButtonsPressed;
void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flags = 0);
bool CompareChecks(RandomizerCheckObject, RandomizerCheckObject);
bool CompareChecks(RandomizerCheck, RandomizerCheck);
bool CheckByArea(RandomizerCheckArea);
void DrawLocation(RandomizerCheckObject);
void DrawLocation(RandomizerCheck);
void EndFloatWindows();
bool HasItemBeenCollected(RandomizerCheck);
void LoadSettings();
@@ -138,6 +141,7 @@ void UpdateInventoryChecks();
void UpdateOrdering(RandomizerCheckArea);
int sectionId;
SceneID DungeonSceneLookupByArea(RandomizerCheckArea area) {
switch (area) {
case RCAREA_DEKU_TREE: return SCENE_DEKU_TREE;
@@ -219,7 +223,7 @@ void GiftFromSages() {
}
}
std::vector<RandomizerCheckObject> checks;
std::vector<RandomizerCheck> checks;
// Function for adding Link's Pocket check
void LinksPocket() {
if (IS_RANDO) {
@@ -234,21 +238,16 @@ void LinksPocket() {
void TrySetAreas() {
if (checksByArea.empty()) {
for (int i = RCAREA_KOKIRI_FOREST; i < RCAREA_INVALID; i++) {
checksByArea.emplace(static_cast<RandomizerCheckArea>(i), std::vector<RandomizerCheckObject>());
checksByArea.emplace(static_cast<RandomizerCheckArea>(i), std::vector<RandomizerCheck>());
}
}
}
void SetCheckCollected(RandomizerCheck rc) {
gSaveContext.checkTrackerData[rc].status = RCSHOW_COLLECTED;
RandomizerCheckObject rcObj;
if (rc == RC_GIFT_FROM_SAGES && !IS_RANDO) {
rcObj = RCO_RAORU;
} else {
rcObj = RandomizerCheckObjects::GetAllRCObjects().find(rc)->second;
}
Rando::Location* loc = Rando::StaticData::GetLocation(rc);
if (!gSaveContext.checkTrackerData[rc].skipped) {
areaChecksGotten[rcObj.rcArea]++;
areaChecksGotten[loc->GetArea()]++;
} else {
gSaveContext.checkTrackerData[rc].skipped = false;
}
@@ -258,7 +257,7 @@ void SetCheckCollected(RandomizerCheck rc) {
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true);
doAreaScroll = true;
UpdateOrdering(rcObj.rcArea);
UpdateOrdering(loc->GetArea());
UpdateInventoryChecks();
}
@@ -359,10 +358,10 @@ bool vector_contains_scene(std::vector<SceneID> vec, const int16_t scene) {
std::vector<SceneID> skipScenes = {SCENE_GANON_BOSS, SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR, SCENE_GANON_BOSS, SCENE_INSIDE_GANONS_CASTLE_COLLAPSE, SCENE_GANONS_TOWER_COLLAPSE_INTERIOR};
bool EvaluateCheck(RandomizerCheckObject rco) {
if (HasItemBeenCollected(rco.rc) && gSaveContext.checkTrackerData[rco.rc].status != RCSHOW_COLLECTED &&
gSaveContext.checkTrackerData[rco.rc].status != RCSHOW_SAVED) {
SetCheckCollected(rco.rc);
bool EvaluateCheck(RandomizerCheck rc) {
if (HasItemBeenCollected(rc) && gSaveContext.checkTrackerData[rc].status != RCSHOW_COLLECTED &&
gSaveContext.checkTrackerData[rc].status != RCSHOW_SAVED) {
SetCheckCollected(rc);
return true;
}
return false;
@@ -378,8 +377,8 @@ bool CheckByArea(RandomizerCheckArea area = RCAREA_INVALID) {
checkCounter = 0;
checkLoops++;
}
auto rco = areaChecks.at(checkCounter);
return EvaluateCheck(rco);
auto rc = areaChecks.at(checkCounter);
return EvaluateCheck(rc);
}
}
@@ -404,8 +403,8 @@ bool HasItemBeenCollected(RandomizerCheck rc) {
if (gPlayState == nullptr) {
return false;
}
ItemLocation* x = Location(rc);
SpoilerCollectionCheck check = x->GetCollectionCheck();
Rando::Location* x = Rando::StaticData::GetLocation(rc);
Rando::SpoilerCollectionCheck check = x->GetCollectionCheck();
auto flag = check.flag;
auto scene = check.scene;
auto type = check.type;
@@ -640,9 +639,9 @@ void CheckTrackerItemReceive(GetItemEntry giEntry) {
void InitTrackerData(bool isDebug) {
TrySetAreas();
for (auto& [rc, rco] : RandomizerCheckObjects::GetAllRCObjects()) {
if (rc != RC_UNKNOWN_CHECK && rc != RC_MAX) {
DefaultCheckData(rc);
for (auto& loc : Rando::StaticData::GetLocationTable()) {
if (loc.GetRandomizerCheck() != RC_UNKNOWN_CHECK && loc.GetRandomizerCheck() != RC_MAX) {
DefaultCheckData(loc.GetRandomizerCheck());
}
}
UpdateAllOrdering();
@@ -689,25 +688,27 @@ void LoadFile() {
});
RandomizerCheckTrackerData entry = gSaveContext.checkTrackerData[i];
RandomizerCheck rc = static_cast<RandomizerCheck>(i);
if (rc == RC_UNKNOWN_CHECK || rc == RC_MAX ||
!RandomizerCheckObjects::GetAllRCObjects().contains(rc))
if (rc == RC_UNKNOWN_CHECK || rc == RC_MAX)
return;
RandomizerCheckObject entry2;
Rando::Location* entry2;
if (rc == RC_GIFT_FROM_SAGES && !IS_RANDO) {
entry2 = RCO_RAORU;
entry2 = Rando::StaticData::GetLocation(rc);
} else {
entry2 = RandomizerCheckObjects::GetAllRCObjects().find(rc)->second;
entry2 = Rando::StaticData::GetLocation(rc);
}
if (!IsVisibleInCheckTracker(entry2)) return;
if (!IsVisibleInCheckTracker(entry2->GetRandomizerCheck())) return;
checksByArea.find(entry2.rcArea)->second.push_back(entry2);
if (entry2->GetRandomizerCheck() != RC_LINKS_POCKET) {
// RC_LINKS_POCKET is a special case because it's RCAREA is different depending on starting age.
checksByArea.find(entry2->GetArea())->second.push_back(entry2->GetRandomizerCheck());
}
if (entry.status == RCSHOW_SAVED || entry.skipped) {
areaChecksGotten[entry2.rcArea]++;
areaChecksGotten[entry2->GetArea()]++;
}
if (areaChecksGotten[entry2.rcArea] != 0 || RandomizerCheckObjects::AreaIsOverworld(entry2.rcArea)) {
areasSpoiled |= (1 << entry2.rcArea);
if (areaChecksGotten[entry2->GetArea()] != 0 || RandomizerCheckObjects::AreaIsOverworld(entry2->GetArea())) {
areasSpoiled |= (1 << entry2->GetArea());
}
});
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) {
@@ -724,9 +725,8 @@ void LoadFile() {
startingArea = RCAREA_KOKIRI_FOREST;
break;
}
RandomizerCheckObject linksPocket = { RC_LINKS_POCKET, RCVORMQ_BOTH, RCTYPE_LINKS_POCKET, startingArea, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, GI_NONE, false, "Link's Pocket", "Link's Pocket" };
checksByArea.find(startingArea)->second.push_back(linksPocket);
checksByArea.find(startingArea)->second.push_back(RC_LINKS_POCKET);
areaChecksGotten[startingArea]++;
}
@@ -756,7 +756,7 @@ void Teardown() {
}
void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) {
auto area = RandomizerCheckObjects::GetAllRCObjects().find(static_cast<RandomizerCheck>(check))->second.rcArea;
auto area = Rando::StaticData::GetLocation(static_cast<RandomizerCheck>(check))->GetArea();
if (!gSaveContext.checkTrackerData[check].skipped && data.skipped) {
areaChecksGotten[area]++;
} else if (gSaveContext.checkTrackerData[check].skipped && !data.skipped) {
@@ -869,10 +869,10 @@ void CheckTrackerWindow::DrawElement() {
std::string stemp;
s32 areaMask = 1;
for (auto& [rcArea, objs] : checksByArea) {
for (auto& [rcArea, checks] : checksByArea) {
RandomizerCheckArea thisArea = currentArea;
const int areaChecksTotal = static_cast<int>(objs.size());
const int areaChecksTotal = static_cast<int>(checks.size());
thisAreaFullyChecked = (areaChecksGotten[rcArea] == areaChecksTotal);
//Last Area needs to be cleaned up
if (lastArea != RCAREA_INVALID && doDraw) {
@@ -942,9 +942,9 @@ void CheckTrackerWindow::DrawElement() {
ImGui::SetScrollHereY(0.0f);
doAreaScroll = false;
}
for (auto rco : objs) {
if (doDraw && isThisAreaSpoiled && IsVisibleInCheckTracker(rco))
DrawLocation(rco);
for (auto rc : checks) {
if (doDraw && isThisAreaSpoiled && IsVisibleInCheckTracker(rc))
DrawLocation(rc);
}
if (doDraw)
ImGui::TreePop();
@@ -1052,6 +1052,8 @@ void LoadSettings() {
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING
:false;
hideShopRightChecks = IS_RANDO ? CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1) : false;
hideTriforceCompleted = IS_RANDO ?
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT) != RO_GENERIC_ON : false;
if (IS_RANDO) {
switch (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TOKENS)) {
@@ -1093,58 +1095,62 @@ void LoadSettings() {
}
}
bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) {
bool IsVisibleInCheckTracker(RandomizerCheck rc) {
Rando::Location* loc = Rando::StaticData::GetLocation(rc);
if (IS_RANDO) {
return
(rcObj.rcArea != RCAREA_INVALID) && // don't show Invalid locations
(rcObj.rcType != RCTYPE_GOSSIP_STONE) && //TODO: Don't show hints until tracker supports them
(rcObj.rcType != RCTYPE_CHEST_GAME) && // don't show non final reward chest game checks until we support shuffling them
(rcObj.rc != RC_HC_ZELDAS_LETTER) && // don't show zeldas letter until we support shuffling it
(rcObj.rc != RC_LINKS_POCKET || showLinksPocket) &&
(!RandomizerCheckObjects::AreaIsDungeon(rcObj.rcArea) ||
rcObj.vOrMQ == RCVORMQ_BOTH ||
rcObj.vOrMQ == RCVORMQ_MQ && OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) ||
rcObj.vOrMQ == RCVORMQ_VANILLA && !OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId)
(loc->GetArea() != RCAREA_INVALID) && // don't show Invalid locations
(loc->GetRCType() != RCTYPE_GOSSIP_STONE) && //TODO: Don't show hints until tracker supports them
(loc->GetRCType() != RCTYPE_CHEST_GAME) && // don't show non final reward chest game checks until we support shuffling them
(rc != RC_HC_ZELDAS_LETTER) && // don't show zeldas letter until we support shuffling it
(rc != RC_LINKS_POCKET || showLinksPocket) &&
(!RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()) ||
loc->GetQuest() == RCQUEST_BOTH ||
loc->GetQuest() == RCQUEST_MQ && OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(loc->GetScene()) ||
loc->GetQuest() == RCQUEST_VANILLA && !OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(loc->GetScene())
) &&
(rcObj.rcType != RCTYPE_SHOP || (showShops && (!hideShopRightChecks || hideShopRightChecks && rcObj.actorParams > 0x03))) &&
(rcObj.rcType != RCTYPE_SCRUB ||
(loc->GetRCType() != RCTYPE_SHOP || (showShops && (!hideShopRightChecks || hideShopRightChecks && loc->GetActorParams() > 0x03))) &&
(loc->GetRandomizerCheck() != RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS) &&
(rc != RC_TRIFORCE_COMPLETED || !hideTriforceCompleted) &&
(rc != RC_GIFT_FROM_SAGES || !IS_RANDO) &&
(loc->GetRCType() != RCTYPE_SCRUB ||
showScrubs ||
rcObj.rc == RC_LW_DEKU_SCRUB_NEAR_BRIDGE || // The 3 scrubs that are always randomized
rcObj.rc == RC_HF_DEKU_SCRUB_GROTTO ||
rcObj.rc == RC_LW_DEKU_SCRUB_GROTTO_FRONT
rc == RC_LW_DEKU_SCRUB_NEAR_BRIDGE || // The 3 scrubs that are always randomized
rc == RC_HF_DEKU_SCRUB_GROTTO ||
rc == RC_LW_DEKU_SCRUB_GROTTO_FRONT
) &&
(rcObj.rcType != RCTYPE_MERCHANT || showMerchants) &&
(rcObj.rcType != RCTYPE_OCARINA || showOcarinas) &&
(rcObj.rcType != RCTYPE_SKULL_TOKEN ||
(showOverworldTokens && RandomizerCheckObjects::AreaIsOverworld(rcObj.rcArea)) ||
(showDungeonTokens && RandomizerCheckObjects::AreaIsDungeon(rcObj.rcArea))
(loc->GetRCType() != RCTYPE_MERCHANT || showMerchants) &&
(loc->GetRCType() != RCTYPE_OCARINA || showOcarinas) &&
(loc->GetRCType() != RCTYPE_SKULL_TOKEN ||
(showOverworldTokens && RandomizerCheckObjects::AreaIsOverworld(loc->GetArea())) ||
(showDungeonTokens && RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()))
) &&
(rcObj.rcType != RCTYPE_COW || showCows) &&
(rcObj.rcType != RCTYPE_ADULT_TRADE ||
(loc->GetRCType() != RCTYPE_COW || showCows) &&
(loc->GetRCType() != RCTYPE_ADULT_TRADE ||
showAdultTrade ||
rcObj.rc == RC_KAK_ANJU_AS_ADULT || // adult trade checks that are always shuffled
rcObj.rc == RC_DMT_TRADE_CLAIM_CHECK // even when shuffle adult trade is off
rc == RC_KAK_ANJU_AS_ADULT || // adult trade checks that are always shuffled
rc == RC_DMT_TRADE_CLAIM_CHECK // even when shuffle adult trade is off
) &&
(rcObj.rc != RC_KF_KOKIRI_SWORD_CHEST || showKokiriSword) &&
(rcObj.rc != RC_ZR_MAGIC_BEAN_SALESMAN || showBeans) &&
(rcObj.rc != RC_HC_MALON_EGG || showWeirdEgg) &&
(rcObj.rcType != RCTYPE_FROG_SONG || showFrogSongRupees) &&
(rcObj.rcType != RCTYPE_MAP_COMPASS || showStartingMapsCompasses) &&
(rcObj.rcType != RCTYPE_SMALL_KEY || showKeysanity) &&
(rcObj.rcType != RCTYPE_BOSS_KEY || showBossKeysanity) &&
(rcObj.rcType != RCTYPE_GANON_BOSS_KEY || showGanonBossKey) &&
(rcObj.rc != RC_KAK_100_GOLD_SKULLTULA_REWARD || show100SkullReward) &&
(rcObj.rcType != RCTYPE_GF_KEY && rcObj.rc != RC_GF_GERUDO_MEMBERSHIP_CARD ||
(showGerudoCard && rcObj.rc == RC_GF_GERUDO_MEMBERSHIP_CARD) ||
(fortressNormal && showGerudoFortressKeys && rcObj.rcType == RCTYPE_GF_KEY) ||
(fortressFast && showGerudoFortressKeys && rcObj.rc == RC_GF_NORTH_F1_CARPENTER)
(rc != RC_KF_KOKIRI_SWORD_CHEST || showKokiriSword) &&
(rc != RC_ZR_MAGIC_BEAN_SALESMAN || showBeans) &&
(rc != RC_HC_MALON_EGG || showWeirdEgg) &&
(loc->GetRCType() != RCTYPE_FROG_SONG || showFrogSongRupees) &&
(loc->GetRCType() != RCTYPE_MAP_COMPASS || showStartingMapsCompasses) &&
(loc->GetRCType() != RCTYPE_SMALL_KEY || showKeysanity) &&
(loc->GetRCType() != RCTYPE_BOSS_KEY || showBossKeysanity) &&
(loc->GetRCType() != RCTYPE_GANON_BOSS_KEY || showGanonBossKey) &&
(rc != RC_KAK_100_GOLD_SKULLTULA_REWARD || show100SkullReward) &&
(loc->GetRCType() != RCTYPE_GF_KEY && rc != RC_GF_GERUDO_MEMBERSHIP_CARD ||
(showGerudoCard && rc == RC_GF_GERUDO_MEMBERSHIP_CARD) ||
(fortressNormal && showGerudoFortressKeys && loc->GetRCType() == RCTYPE_GF_KEY) ||
(fortressFast && showGerudoFortressKeys && rc == RC_GF_NORTH_F1_CARPENTER)
);
}
else if (rcObj.vanillaCompletion) {
return (rcObj.vOrMQ == RCVORMQ_BOTH ||
rcObj.vOrMQ == RCVORMQ_MQ && OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) ||
rcObj.vOrMQ == RCVORMQ_VANILLA && !OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) ||
rcObj.rc == RC_GIFT_FROM_SAGES) && rcObj.rc != RC_LINKS_POCKET;
else if (loc->IsVanillaCompletion()) {
return (loc->GetQuest() == RCQUEST_BOTH ||
loc->GetQuest() == RCQUEST_MQ && OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(loc->GetScene()) ||
loc->GetQuest() == RCQUEST_VANILLA && !OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(loc->GetScene()) ||
rc == RC_GIFT_FROM_SAGES) && rc != RC_LINKS_POCKET;
}
return false;
}
@@ -1183,9 +1189,11 @@ bool IsEoDCheck(RandomizerCheckType type) {
return type == RCTYPE_BOSS_HEART_OR_OTHER_REWARD || type == RCTYPE_DUNGEON_REWARD;
}
bool CompareChecks(RandomizerCheckObject i, RandomizerCheckObject j) {
RandomizerCheckTrackerData iShow = gSaveContext.checkTrackerData[i.rc];
RandomizerCheckTrackerData jShow = gSaveContext.checkTrackerData[j.rc];
bool CompareChecks(RandomizerCheck i, RandomizerCheck j) {
RandomizerCheckTrackerData iShow = gSaveContext.checkTrackerData[i];
RandomizerCheckTrackerData jShow = gSaveContext.checkTrackerData[j];
Rando::Location* x = Rando::StaticData::GetLocation(i);
Rando::Location* y = Rando::StaticData::GetLocation(j);
bool iCollected = iShow.status == RCSHOW_COLLECTED || iShow.status == RCSHOW_SAVED;
bool iSaved = iShow.status == RCSHOW_SAVED;
bool jCollected = jShow.status == RCSHOW_COLLECTED || jShow.status == RCSHOW_SAVED;
@@ -1205,14 +1213,14 @@ bool CompareChecks(RandomizerCheckObject i, RandomizerCheckObject j) {
else if (iShow.skipped && !jShow.skipped)
return false;
if (!IsEoDCheck(i.rcType) && IsEoDCheck(j.rcType))
if (!IsEoDCheck(x->GetRCType()) && IsEoDCheck(y->GetRCType()))
return true;
else if (IsEoDCheck(i.rcType) && !IsEoDCheck(j.rcType))
else if (IsEoDCheck(x->GetRCType()) && !IsEoDCheck(y->GetRCType()))
return false;
if (i.rc < j.rc)
if (x->GetRandomizerCheck() < y->GetRandomizerCheck())
return true;
else if (i.rc > j.rc)
else if (x->GetRandomizerCheck() > y->GetRandomizerCheck())
return false;
return false;
@@ -1222,68 +1230,81 @@ bool IsHeartPiece(GetItemID giid) {
return giid == GI_HEART_PIECE || giid == GI_HEART_PIECE_WIN;
}
void DrawLocation(RandomizerCheckObject rcObj) {
void DrawLocation(RandomizerCheck rc) {
Color_RGBA8 mainColor;
Color_RGBA8 extraColor;
std::string txt;
bool showHidden = CVarGetInteger("gCheckTrackerOptionShowHidden", 0);
RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rcObj.rc];
Rando::Location* loc = Rando::StaticData::GetLocation(rc);
RandomizerCheckTrackerData checkData = gSaveContext.checkTrackerData[rc];
RandomizerCheckStatus status = checkData.status;
bool skipped = checkData.skipped;
if (status == RCSHOW_COLLECTED) {
if (!showHidden && CVarGetInteger("gCheckTrackerCollectedHide", 0))
return;
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerCollectedExtraColor", Color_Collected_Extra_Default) :
CVarGetColor("gCheckTrackerCollectedMainColor", Color_Main_Default);
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? CVarGetColor("gCheckTrackerCollectedExtraColor", Color_Collected_Extra_Default)
: CVarGetColor("gCheckTrackerCollectedMainColor", Color_Main_Default);
extraColor = CVarGetColor("gCheckTrackerCollectedExtraColor", Color_Collected_Extra_Default);
} else if (status == RCSHOW_SAVED) {
if (!showHidden && CVarGetInteger("gCheckTrackerSavedHide", 0))
return;
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSavedExtraColor", Color_Saved_Extra_Default) :
CVarGetColor("gCheckTrackerSavedMainColor", Color_Main_Default);
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? CVarGetColor("gCheckTrackerSavedExtraColor", Color_Saved_Extra_Default)
: CVarGetColor("gCheckTrackerSavedMainColor", Color_Main_Default);
extraColor = CVarGetColor("gCheckTrackerSavedExtraColor", Color_Saved_Extra_Default);
} else if (skipped) {
if (!showHidden && CVarGetInteger("gCheckTrackerSkippedHide", 0))
return;
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSkippedExtraColor", Color_Skipped_Extra_Default) :
CVarGetColor("gCheckTrackerSkippedMainColor", Color_Main_Default);
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? CVarGetColor("gCheckTrackerSkippedExtraColor", Color_Skipped_Extra_Default)
: CVarGetColor("gCheckTrackerSkippedMainColor", Color_Main_Default);
extraColor = CVarGetColor("gCheckTrackerSkippedExtraColor", Color_Skipped_Extra_Default);
} else if (status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED) {
if (!showHidden && CVarGetInteger("gCheckTrackerSeenHide", 0))
return;
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default) :
CVarGetColor("gCheckTrackerSeenMainColor", Color_Main_Default);
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default)
: CVarGetColor("gCheckTrackerSeenMainColor", Color_Main_Default);
extraColor = CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default);
} else if (status == RCSHOW_SCUMMED) {
if (!showHidden && CVarGetInteger("gCheckTrackerKnownHide", 0))
return;
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default) :
CVarGetColor("gCheckTrackerScummedMainColor", Color_Main_Default);
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default)
: CVarGetColor("gCheckTrackerScummedMainColor", Color_Main_Default);
extraColor = CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default);
} else if (status == RCSHOW_UNCHECKED) {
if (!showHidden && CVarGetInteger("gCheckTrackerUncheckedHide", 0))
return;
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default) :
CVarGetColor("gCheckTrackerUncheckedMainColor", Color_Main_Default);
mainColor =
!IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID()) && !IS_RANDO
? CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default)
: CVarGetColor("gCheckTrackerUncheckedMainColor", Color_Main_Default);
extraColor = CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default);
}
//Main Text
txt = rcObj.rcShortName;
if (lastLocationChecked == rcObj.rc)
txt = loc->GetShortName();
if (lastLocationChecked == loc->GetRandomizerCheck())
txt = "* " + txt;
// Draw button - for Skipped/Seen/Scummed/Unchecked only
if (status == RCSHOW_UNCHECKED || status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED || status == RCSHOW_SCUMMED || skipped) {
if (UIWidgets::StateButton(std::to_string(rcObj.rc).c_str(), skipped ? ICON_FA_PLUS : ICON_FA_TIMES)) {
if (UIWidgets::StateButton(std::to_string(rc).c_str(), skipped ? ICON_FA_PLUS : ICON_FA_TIMES)) {
if (skipped) {
gSaveContext.checkTrackerData[rcObj.rc].skipped = false;
areaChecksGotten[rcObj.rcArea]--;
gSaveContext.checkTrackerData[rc].skipped = false;
areaChecksGotten[loc->GetArea()]--;
} else {
gSaveContext.checkTrackerData[rcObj.rc].skipped = true;
areaChecksGotten[rcObj.rcArea]++;
gSaveContext.checkTrackerData[rc].skipped = true;
areaChecksGotten[loc->GetArea()]++;
}
UpdateOrdering(rcObj.rcArea);
UpdateOrdering(loc->GetArea());
UpdateInventoryChecks();
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true);
}
@@ -1308,13 +1329,13 @@ void DrawLocation(RandomizerCheckObject rcObj) {
case RCSHOW_COLLECTED:
case RCSHOW_SCUMMED:
if (IS_RANDO) {
txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rcObj.rc].get.rgID][gSaveContext.language];
txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rc].get.rgID][gSaveContext.language];
} else {
if (IsHeartPiece(rcObj.ogItemId)) {
if (IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID())) {
if (gSaveContext.language == LANGUAGE_ENG || gSaveContext.language == LANGUAGE_GER) {
txt = ItemFromGIID(rcObj.ogItemId).GetName().english;
txt = Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetName().english;
} else if (gSaveContext.language == LANGUAGE_FRA) {
txt = ItemFromGIID(rcObj.ogItemId).GetName().french;
txt = Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetName().french;
}
}
}
@@ -1322,24 +1343,24 @@ void DrawLocation(RandomizerCheckObject rcObj) {
case RCSHOW_IDENTIFIED:
case RCSHOW_SEEN:
if (IS_RANDO) {
if (gSaveContext.itemLocations[rcObj.rc].get.rgID == RG_ICE_TRAP) {
if (gSaveContext.itemLocations[rc].get.rgID == RG_ICE_TRAP) {
if (status == RCSHOW_IDENTIFIED) {
txt = gSaveContext.itemLocations[rcObj.rc].get.trickName;
txt = gSaveContext.itemLocations[rc].get.trickName;
} else {
txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rcObj.rc].get.fakeRgID][gSaveContext.language];
txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rc].get.fakeRgID][gSaveContext.language];
}
} else {
txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rcObj.rc].get.rgID][gSaveContext.language];
txt = OTRGlobals::Instance->gRandomizer->EnumToSpoilerfileGetName[gSaveContext.itemLocations[rc].get.rgID][gSaveContext.language];
}
if (status == RCSHOW_IDENTIFIED) {
txt += fmt::format(" - {}", gSaveContext.checkTrackerData[rcObj.rc].price);
txt += fmt::format(" - {}", gSaveContext.checkTrackerData[rc].price);
}
} else {
if (IsHeartPiece(rcObj.ogItemId)) {
if (IsHeartPiece((GetItemID)Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetItemID())) {
if (gSaveContext.language == LANGUAGE_ENG || gSaveContext.language == LANGUAGE_GER) {
txt = ItemFromGIID(rcObj.ogItemId).GetName().english;
txt = Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetName().english;
} else if (gSaveContext.language == LANGUAGE_FRA) {
txt = ItemFromGIID(rcObj.ogItemId).GetName().french;
txt = Rando::StaticData::RetrieveItem(loc->GetVanillaItem()).GetName().french;
}
}
}
@@ -1534,7 +1555,7 @@ void CheckTrackerWindow::InitElement() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(CheckTrackerTransition);
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnShopSlotChange>(CheckTrackerShopSlotChange);
LocationTable_Init();
//LocationTable_Init();
}
} // namespace CheckTracker

View File

@@ -46,7 +46,7 @@ class CheckTrackerWindow : public LUS::GuiWindow {
void DefaultCheckData(RandomizerCheck rc);
void Teardown();
void UpdateAllOrdering();
bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj);
bool IsVisibleInCheckTracker(RandomizerCheck rc);
void InitTrackerData(bool isDebug);
void SetLastItemGetRC(RandomizerCheck rc);
RandomizerCheckArea GetCheckArea();

View File

@@ -0,0 +1,37 @@
#pragma once
#include <array>
#include "randomizerTypes.h"
#include "item.h"
#include "location.h"
namespace Rando {
/**
* @brief Singleton for storing and accessing static Randomizer-related data
*
* The StaticData class is a class for storing and accessing static Randomizer-related data.
* Static Data, in this context, refers to data that is the same for every single randomizer seed,
* i.e. the item and location tables. This class is intended to be used as a Singleton.
*/
class StaticData {
private:
static std::array<Item, RG_MAX> itemTable;
static std::array<Location, RC_MAX> locationTable;
public:
static void InitItemTable();
static Item& RetrieveItem(const RandomizerGet rgid);
static Item& ItemFromGIID(const int giid);
static std::array<Item, RG_MAX>& GetItemTable();
static void InitLocationTable();
static Location* GetLocation(RandomizerCheck locKey);
static std::array<Rando::Location, RC_MAX>& GetLocationTable();
static std::vector<RandomizerCheck> overworldLocations;
static std::vector<RandomizerCheck> dungeonRewardLocations;
static std::vector<std::vector<RandomizerCheck>> shopLocationLists;
static std::vector<RandomizerCheck> scrubLocations;
static std::vector<RandomizerCheck> gossipStoneLocations;
StaticData();
~StaticData();
};
}

View File

@@ -40,6 +40,7 @@
#include "Enhancements/randomizer/randomizer_item_tracker.h"
#include "Enhancements/randomizer/randomizer_check_tracker.h"
#include "Enhancements/randomizer/3drando/random.hpp"
#include "Enhancements/randomizer/static_data.h"
#include "Enhancements/gameplaystats.h"
#include "Enhancements/n64_weird_frame_data.inc"
#include "frame_interpolation.h"
@@ -265,6 +266,7 @@ OTRGlobals::OTRGlobals() {
context->GetResourceManager()->GetResourceLoader()->RegisterResourceFactory(LUS::ResourceType::SOH_Background, "Background", std::make_shared<LUS::BackgroundFactory>());
gSaveStateMgr = std::make_shared<SaveStateMgr>();
gRandoContext = Rando::Context::CreateInstance();
gRandomizer = std::make_shared<Randomizer>();
hasMasterQuest = hasOriginal = false;

View File

@@ -17,6 +17,7 @@
#include "Enhancements/savestates.h"
#include "Enhancements/randomizer/randomizer.h"
#include <vector>
#include "Enhancements/randomizer/context.h"
const std::string customMessageTableID = "BaseGameOverrides";
const std::string appShortName = "soh";
@@ -29,6 +30,7 @@ public:
std::shared_ptr<LUS::Context> context;
std::shared_ptr<SaveStateMgr> gSaveStateMgr;
std::shared_ptr<Randomizer> gRandomizer;
std::shared_ptr<Rando::Context> gRandoContext;
OTRGlobals();
~OTRGlobals();