mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-01-30 15:00:13 -05:00
testing out item replacement (#416)
* skip learning song of storms * don't set flag when getting goron tunic as child * Initiates prelude check when master sword unloads. Not quite how N64 rando does it but so far it's the only way I've found to make it trigger without also triggering the time travel again. * Stops Shadow Temple lore prompts from appearing in rando. * Skips cutscene of royal tomb explosion in rando. Explosion sound doesn't play correctly and I think the debris appears in the wrong place, but the functionality is here. * Improves visual of exploding gravestone. * Adds some comments explaining the rando differences * Skip ruto text box in jabu blue warp For rando * skip intro cutscene in dodongo's cavern * load spoiler files on boot, fix spoilerfile existing check when making new saves * name entry dropped spoiler logic * make sure to actually init the cvar * no chime on load * uncomment * Skip ganondrof cutscene Skip to scream part of the death animation, skipping the text boxes etc. For rando * Update z_boss_ganondrof.c * skip owl flight cutscenes in rando * Fixes skipped text so it only applies to shadow temple. Earlier fix inadvertently applied to some other text as well, changed logic so that only specified sceneNums and textIds can have this enabled, and text skipped by sceneNum can have the skip overriden by textId if needed. Currently there are no overrides so the textId section of the logic is commented out to avoid compilation errors. * Adds a default to the switch case statements that leaves the randoSkipText variable unchanged, just in case. * TEST: Text for item * Adding ganon flavor text * ADD: AMMO Count * format ganon text/hint text * Autoskip the tower cutscene if settings call for tower collapse. * ganon hint text logic * Improved prelude after time travel fix * swapped the sizes between ganon hint text and ganon text, as they were set to the wrong things. * this is all i did * not the cleanest code ever but it's working * ADD: GS Count * ADD: Wallter (crash for now) * TWEAK: Wallet check * FIX: Use DrawItem instread of DrawUpgrade... b-baka! * Fixes some vanilla bugs introduced by rando code. * Added cutscene skip for zelda escaping Using the debug cutscene skipping function. Also added a conditional so the bridge doesn't spawn closed when cutscene is ready to trigger * ADD: X Spacing + Placeholders for song * ADD: default case for items * TWEAK: Spacing * FIX: Light Arrow * ADD: Ammo Option * use groups instead * ADD: More spacing logic * songs and names * TWEAK: Color on wallet * colors * Added flags cutscene before nabooru fight * ADD: ChromaKey text * First attempt skip cs after nabooru defeat * Better implementation for specific rando cutscene skips * use pulseaudio defaults * spaces/tabs * move color push/pop to stop crash * make the colors work again * the real bottle fix * pulseaudio values tuned for n64 audio at 44.1khz * update tlength * remove one hardcoded samplerate * Cleaned up and fixed zelda escape skip The if statement is a freaking monster, but unless we want to skip more cutscenes in the same way later, this is the most compact way of doing it that I know of. * Revert one line to match original nothing functional * another hint line that breaks autonewline logic * don't autospawn epona if we don't have the song/ocarina * Trying to use iron knuckle death effects not working yet * Streamlined OoT cutscene skip for future additions Also cleaned up if statement in general * Made if statement more readable Also added clarity for what cutscene was skipped * Fixed typo in comment * Janky nabooru defeat cs skip * altar text formatting (gonna need help shortening some of the french ones) * more altar text formatting * english altar text formatting complete * make gtg blocking guard check for card not bridge * FIX: Typo! * FIX: Uppercases * FIX: Typo * TWEAK: Alter + some names * TWEAK: More caps! * ADD: Missing string TWEAK more uppercases and namefixe s * Hide nabooru death by covering her in flames * bandaid fix for death crash issue * Twinrova defeat cs skip Skips the animation and manually calls the function to show the "beam" around the sisters * fix crash * fix caps to match * fix great fairy reward mashing/shielding issue * TWEAK : Typo clé to Clé * TWEAK: Some Altar hints TWEAK: Some capitals * TWEAK: Unmatching text + some cap again * TWEAK: More tweaks * fix build * remove extra json.hpp, add hint * Update randomizer_item_tracker.cpp * TWEAK: Double Defense with RedParticles instead of white * make sure we don't optimize out the check to ensure a spoilerfile exists * vanilla ganon boss key hint formatting * TWEAK: FR- better way of the hero text * fix * and again * Initializes dungeonsDone items in gSaveContext to 0. * Replaces sizeof calculation with a NUM_DUNGEONS constant. * Fixes Saria's Gift on the LW Bridge from getting killed when holding shield. * More airtight fix for Saria's Gift on the Bridge. * Lifts one of the conditions in the if statement a little higher to prevent unnecessary lookups of getItemId. * Invalidate text box icon before drawing * Fixes the case where Saria's gift is an Ice Trap. We still get the Ice Trap once, but never again. This does mean you can now hold R while walking in to avoid the ice trap, but everything else seems to work fine. * Initial commit Might need changing when we change the settings in the future * Fixes Door of Time opening cutscene after warping with prelude. * Initial waterfall skip Very rudimentary way of doing things but it seems to work so 🤷 * inital rework * fixed default rotation for 2D sprites * fix tab/space issues * 3d drops rando merge fix again * Allows Impa to appear in the Lullaby check post drawbridge escape. * Changes Ganon's Trials Count setting to a checkbox The checkbox is whether or not to skip all of them. Leaving the box unchecked will mean doing all of them. Eventually this will be switched back to a slider once we implement the logic for which trials start out completed. * Sets all Ganon's Trials to incomplete in new saves. Fixes https://github.com/briaguya-ai/rando-issue-tracker/issues/131 * fix castle guards when oot throw cutscene has already played in rando * Properly removes the beams when trials are cleared. * Removes Question Mark from Skip Ganon's Trials UI. * Adds a todo comment about when to change back to slider. * make deku seeds check for bullet bag * Various tweaks TWEAK: Altar Text TWEAK: Hint names TWEAK: Replace more problematic œ to oe * upgrade ocarina on both child and adult equips * FIX: Jabu Item * update equipped hookshot/longshot when obtained as other age * add hint * don't give the bgs check without the claim check * Skips Darunia Cutscene in Fire Temple * Added a TODO note about not skipping the cutscene. There is a setting we will want to have eventually that will require this cutscene to not be skipped since it is used during a glitch. * remove todo * restore fast ocarina option in imgui that was lost in merge * Fixes grey screen issue + tooltip for 2 handed shield * update to use dg instead of g for textures in item tracker * TWEAK: Default color for cosmetic RAND button was not the corect one * fix texture crash, remove unused item tracker code * don't open mask shop until we get zelda's letter * Update README.md * Prevents "correct" chime under incorrect conditions. * Fixes typo in conditional and adds "bonk" sound effect. "Bonk" sound is NA_SE_SY_OCARINA_ERROR and it plays when conditions for the Door of Time have not been met after playing Song of Time. This is only possible in rando's "Intended" Door of Time option, in which the Ocarina of Time and all 3 spritual stones are required to open the door, instead of the vanilla requirements of just having the song of time. * remove modify dpad equips toggle, replace with checks for dpad menu * remove extra check * add ability to hold c-up to assign to dpad when dpad menuing is enabled * disable d-pad navigation on item menu when holding c-up to equip * dpad+c-up stuff for equipment menu * ADD: Checbox for songs colors * TWEAK: RandoColors for normal songs * kind of quick and dirty but it works * TWEAK: Clarity of the tooltip Co-authored-by: briaguya <briaguya@alice> Co-authored-by: Christopher Leggett <chris@leggett.dev> Co-authored-by: aMannus <mannusmenting@gmail.com> Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com> Co-authored-by: Dog <5172592+Dog@users.noreply.github.com> Co-authored-by: Vague Rant <vaguerant@users.noreply.github.com> Co-authored-by: Baoulettes <perlouzerie@hotmail.fr> Co-authored-by: Ada <60364512+GreatArgorath@users.noreply.github.com>
This commit is contained in:
parent
0fd779f002
commit
c25089b98f
@ -128,5 +128,3 @@ Nightly builds of Ship of Harkinian are available [here](https://builds.shipofha
|
||||
MicTheMicrophone | Gwonam / The King
|
||||
Amphibibro | Link
|
||||
AceHeart | Zelda
|
||||
|
||||
###### Lemons
|
||||
|
@ -64,7 +64,7 @@ void CVar_SetFloat(const char* name, float value) {
|
||||
cvar->value.valueFloat = value;
|
||||
}
|
||||
|
||||
void CVar_SetString(const char* name, const char* value) {
|
||||
extern "C" void CVar_SetString(const char* name, const char* value) {
|
||||
auto& cvar = cvars[name];
|
||||
if (!cvar) {
|
||||
cvar = std::make_unique<CVar>();
|
||||
|
@ -27,6 +27,7 @@ s32 CVar_GetS32(const char* name, s32 defaultValue);
|
||||
float CVar_GetFloat(const char* name, float defaultValue);
|
||||
const char* CVar_GetString(const char* name, const char* defaultValue);
|
||||
void CVar_SetS32(const char* name, s32 value);
|
||||
void CVar_SetString(const char* name, const char* value);
|
||||
|
||||
void CVar_RegisterS32(const char* name, s32 defaultValue);
|
||||
void CVar_RegisterFloat(const char* name, float defaultValue);
|
||||
@ -44,6 +45,5 @@ void CVar_RegisterString(const char* name, const char* defaultValue);
|
||||
|
||||
extern std::map<std::string, std::unique_ptr<CVar>, std::less<>> cvars;
|
||||
void CVar_SetFloat(const char* name, float value);
|
||||
void CVar_SetString(const char* name, const char* value);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -56,7 +56,7 @@ namespace Game {
|
||||
void InitSettings() {
|
||||
ModInternal::RegisterHook<ModInternal::AudioInit>(UpdateAudio);
|
||||
ModInternal::RegisterHook<ModInternal::GfxInit>([] {
|
||||
gfx_get_current_rendering_api()->set_texture_filter((FilteringMode) CVar_GetS32("gTextureFilter", THREE_POINT));
|
||||
gfx_get_current_rendering_api()->set_texture_filter((FilteringMode) CVar_GetS32("gTextureFilter", FILTER_THREE_POINT));
|
||||
SohImGui::console->opened = CVar_GetS32("gConsoleEnabled", 0);
|
||||
UpdateAudio();
|
||||
});
|
||||
|
@ -276,12 +276,12 @@ namespace SohImGui {
|
||||
u8 b = (current_hue / 60.0f + (1 - i)) * 255;
|
||||
|
||||
switch (i) {
|
||||
case 1: NewColor.x = 255; NewColor.y = b; NewColor.z = 0; break;
|
||||
case 2: NewColor.x = a; NewColor.y = 255; NewColor.z = 0; break;
|
||||
case 3: NewColor.x = 0; NewColor.y = 255; NewColor.z = b; break;
|
||||
case 4: NewColor.x = 0; NewColor.y = a; NewColor.z = 255; break;
|
||||
case 5: NewColor.x = b; NewColor.y = 0; NewColor.z = 255; break;
|
||||
case 6: NewColor.x = 255; NewColor.y = 0; NewColor.z = a; break;
|
||||
case 1: NewColor.x = 255; NewColor.y = b; NewColor.z = 0; break;
|
||||
case 2: NewColor.x = a; NewColor.y = 255; NewColor.z = 0; break;
|
||||
case 3: NewColor.x = 0; NewColor.y = 255; NewColor.z = b; break;
|
||||
case 4: NewColor.x = 0; NewColor.y = a; NewColor.z = 255; break;
|
||||
case 5: NewColor.x = b; NewColor.y = 0; NewColor.z = 255; break;
|
||||
case 6: NewColor.x = 255; NewColor.y = 0; NewColor.z = a; break;
|
||||
}
|
||||
|
||||
if (CVar_GetS32(Cvar_RBM.c_str(), 0) != 0) {
|
||||
@ -389,7 +389,7 @@ namespace SohImGui {
|
||||
LoadTexture("C-Right", "assets/ship_of_harkinian/buttons/CRight.png");
|
||||
LoadTexture("C-Up", "assets/ship_of_harkinian/buttons/CUp.png");
|
||||
LoadTexture("C-Down", "assets/ship_of_harkinian/buttons/CDown.png");
|
||||
});
|
||||
});
|
||||
|
||||
for (const auto& [i, controllers] : Ship::Window::Controllers)
|
||||
{
|
||||
@ -400,8 +400,14 @@ namespace SohImGui {
|
||||
|
||||
ModInternal::RegisterHook<ModInternal::ControllerRead>([](OSContPad* cont_pad) {
|
||||
pads = cont_pad;
|
||||
});
|
||||
});
|
||||
Game::InitSettings();
|
||||
|
||||
CVar_SetS32("gRandoGenerating", 0);
|
||||
CVar_SetS32("gNewSeedGenerated", 0);
|
||||
CVar_SetS32("gNewFileDropped", 0);
|
||||
CVar_SetString("gDroppedFile", "");
|
||||
Game::SaveSettings();
|
||||
}
|
||||
|
||||
void Update(EventImpl event) {
|
||||
@ -492,9 +498,9 @@ namespace SohImGui {
|
||||
}
|
||||
}
|
||||
|
||||
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format)
|
||||
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue)
|
||||
{
|
||||
int val = CVar_GetS32(cvarName, 0);
|
||||
int val = CVar_GetS32(cvarName, defaultValue);
|
||||
|
||||
ImGui::Text(text, val);
|
||||
|
||||
@ -662,8 +668,7 @@ namespace SohImGui {
|
||||
CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(ColorRGBA.z * 255, 0, 255));
|
||||
needs_save = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (ImGui::ColorEdit4(text, (float*)&ColorRGBA, flags)) {
|
||||
CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(ColorRGBA.x * 255, 0, 255));
|
||||
CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(ColorRGBA.y * 255, 0, 255));
|
||||
@ -800,14 +805,13 @@ namespace SohImGui {
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// TODO mutual exclusions -- gDpadEquips and gDpadPauseName cause conflicts, but nothing stops a user from selecting both
|
||||
// There should be some system to prevent conclifting enhancements from being selected
|
||||
// TODO mutual exclusions -- There should be some system to prevent conclifting enhancements from being selected
|
||||
EnhancementCheckbox("D-pad Support on Pause and File Select", "gDpadPauseName");
|
||||
Tooltip("Enables Pause and File Select screen navigation with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up\nto equip instead of navigate");
|
||||
EnhancementCheckbox("D-pad Support in Ocarina and Text Choice", "gDpadOcarinaText");
|
||||
EnhancementCheckbox("D-pad Support for Browsing Shop Items", "gDpadShop");
|
||||
EnhancementCheckbox("D-pad as Equip Items", "gDpadEquips");
|
||||
Tooltip("Allows the D-pad to be used as extra C buttons\nNote: Incompatible with D-pad on pause and file select");
|
||||
|
||||
Tooltip("Allows the D-pad to be used as extra C buttons");
|
||||
ImGui::Separator();
|
||||
|
||||
EnhancementCheckbox("Show Inputs", "gInputEnabled");
|
||||
@ -931,7 +935,9 @@ namespace SohImGui {
|
||||
Tooltip("Skip first-time pickup messages for consumable items");
|
||||
EnhancementCheckbox("Better Owl", "gBetterOwl");
|
||||
Tooltip("The default response to Kaepora Gaebora is\nalways that you understood what he said");
|
||||
|
||||
EnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback");
|
||||
Tooltip("Skip the part where the Ocarina playback is called when you play\na song");
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@ -1007,7 +1013,19 @@ namespace SohImGui {
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
|
||||
if (ImGui::BeginMenu("Fishing")) {
|
||||
EnhancementCheckbox("Instant Fishing", "gInstantFishing");
|
||||
Tooltip("All fish will be caught instantly");
|
||||
EnhancementCheckbox("Guarantee Bite", "gGuaranteeFishingBite");
|
||||
Tooltip("When a line is stable, guarantee bite. Otherwise use default logic");
|
||||
EnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 6, 10, "", 10);
|
||||
Tooltip("The minimum weight for the unique fishing reward as a child");
|
||||
EnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 8, 13, "", 13);
|
||||
Tooltip("The minimum weight for the unique fishing reward as an adult");
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@ -1033,6 +1051,8 @@ namespace SohImGui {
|
||||
EnhancementCheckbox("Enable passage of time on file select", "gTimeFlowFileSelect");
|
||||
EnhancementCheckbox("Allow the cursor to be on any slot", "gPauseAnyCursor");
|
||||
Tooltip("Allows the cursor on the pause menu to be over any slot\nSimilar to Rando and Spaceworld 97");
|
||||
EnhancementCheckbox("Count Golden Skulltulas", "gInjectSkulltulaCount");
|
||||
Tooltip("Injects Golden Skulltula total count in pickup messages");
|
||||
EnhancementCheckbox("Pull grave during the day", "gDayGravePull");
|
||||
Tooltip("Allows graves to be pulled when child during the day");
|
||||
ImGui::EndMenu();
|
||||
|
@ -68,7 +68,7 @@ namespace SohImGui {
|
||||
void EnhancementRadioButton(const char* text, const char* cvarName, int id);
|
||||
void EnhancementCheckbox(const char* text, const char* cvarName);
|
||||
void EnhancementButton(const char* text, const char* cvarName);
|
||||
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format);
|
||||
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0);
|
||||
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage);
|
||||
void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue);
|
||||
void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false);
|
||||
|
@ -137,7 +137,7 @@ static struct {
|
||||
//uint32_t current_width, current_height;
|
||||
uint32_t render_target_height;
|
||||
int current_framebuffer;
|
||||
FilteringMode current_filter_mode = NONE;
|
||||
FilteringMode current_filter_mode = FILTER_NONE;
|
||||
|
||||
int8_t depth_test;
|
||||
int8_t depth_mask;
|
||||
@ -413,7 +413,7 @@ static struct ShaderProgram *gfx_d3d11_create_and_load_new_shader(uint64_t shade
|
||||
char buf[4096];
|
||||
size_t len, num_floats;
|
||||
|
||||
gfx_direct3d_common_build_shader(buf, len, num_floats, cc_features, false, d3d.current_filter_mode == THREE_POINT);
|
||||
gfx_direct3d_common_build_shader(buf, len, num_floats, cc_features, false, d3d.current_filter_mode == FILTER_THREE_POINT);
|
||||
|
||||
ComPtr<ID3DBlob> vs, ps;
|
||||
ComPtr<ID3DBlob> error_blob;
|
||||
@ -580,7 +580,7 @@ static void gfx_d3d11_set_sampler_parameters(int tile, bool linear_filter, uint3
|
||||
D3D11_SAMPLER_DESC sampler_desc;
|
||||
ZeroMemory(&sampler_desc, sizeof(D3D11_SAMPLER_DESC));
|
||||
|
||||
sampler_desc.Filter = linear_filter && d3d.current_filter_mode == LINEAR ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
sampler_desc.Filter = linear_filter && d3d.current_filter_mode == FILTER_LINEAR ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
|
||||
sampler_desc.AddressU = gfx_cm_to_d3d11(cms);
|
||||
sampler_desc.AddressV = gfx_cm_to_d3d11(cmt);
|
||||
@ -685,7 +685,7 @@ static void gfx_d3d11_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t
|
||||
d3d.last_resource_views[i] = d3d.textures[d3d.current_texture_ids[i]].resource_view.Get();
|
||||
d3d.context->PSSetShaderResources(i, 1, d3d.textures[d3d.current_texture_ids[i]].resource_view.GetAddressOf());
|
||||
|
||||
if (d3d.current_filter_mode == THREE_POINT) {
|
||||
if (d3d.current_filter_mode == FILTER_THREE_POINT) {
|
||||
d3d.per_draw_cb_data.textures[i].width = d3d.textures[d3d.current_texture_ids[i]].width;
|
||||
d3d.per_draw_cb_data.textures[i].height = d3d.textures[d3d.current_texture_ids[i]].height;
|
||||
d3d.per_draw_cb_data.textures[i].linear_filtering = d3d.textures[d3d.current_texture_ids[i]].linear_filtering;
|
||||
|
@ -27,9 +27,11 @@
|
||||
#include "gfx_screen_config.h"
|
||||
#include "gfx_pc.h"
|
||||
#include "../../ImGuiImpl.h"
|
||||
#include "../../Cvar.h"
|
||||
|
||||
#define DECLARE_GFX_DXGI_FUNCTIONS
|
||||
#include "gfx_dxgi.h"
|
||||
#include "../../GameSettings.h"
|
||||
|
||||
#define WINCLASS_NAME L"N64GAME"
|
||||
#define GFX_API_NAME "DirectX"
|
||||
@ -85,8 +87,8 @@ static struct {
|
||||
|
||||
static void load_dxgi_library(void) {
|
||||
dxgi.dxgi_module = LoadLibraryW(L"dxgi.dll");
|
||||
*(FARPROC *)&dxgi.CreateDXGIFactory1 = GetProcAddress(dxgi.dxgi_module, "CreateDXGIFactory1");
|
||||
*(FARPROC *)&dxgi.CreateDXGIFactory2 = GetProcAddress(dxgi.dxgi_module, "CreateDXGIFactory2");
|
||||
*(FARPROC*)&dxgi.CreateDXGIFactory1 = GetProcAddress(dxgi.dxgi_module, "CreateDXGIFactory1");
|
||||
*(FARPROC*)&dxgi.CreateDXGIFactory2 = GetProcAddress(dxgi.dxgi_module, "CreateDXGIFactory2");
|
||||
}
|
||||
|
||||
template <typename Fun>
|
||||
@ -110,8 +112,8 @@ static void run_as_dpi_aware(Fun f) {
|
||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)
|
||||
#define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ((DPI_AWARENESS_CONTEXT)-5)
|
||||
|
||||
DPI_AWARENESS_CONTEXT (WINAPI *SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT dpiContext);
|
||||
*(FARPROC *)&SetThreadDpiAwarenessContext = GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetThreadDpiAwarenessContext");
|
||||
DPI_AWARENESS_CONTEXT(WINAPI * SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT dpiContext);
|
||||
*(FARPROC*)&SetThreadDpiAwarenessContext = GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetThreadDpiAwarenessContext");
|
||||
DPI_AWARENESS_CONTEXT old_awareness_context = nullptr;
|
||||
if (SetThreadDpiAwarenessContext != nullptr) {
|
||||
old_awareness_context = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
@ -121,8 +123,8 @@ static void run_as_dpi_aware(Fun f) {
|
||||
if (!dxgi.process_dpi_awareness_done) {
|
||||
HMODULE shcore_module = LoadLibraryW(L"SHCore.dll");
|
||||
if (shcore_module != nullptr) {
|
||||
HRESULT (WINAPI *SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value);
|
||||
*(FARPROC *)&SetProcessDpiAwareness = GetProcAddress(shcore_module, "SetProcessDpiAwareness");
|
||||
HRESULT(WINAPI * SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value);
|
||||
*(FARPROC*)&SetProcessDpiAwareness = GetProcAddress(shcore_module, "SetProcessDpiAwareness");
|
||||
if (SetProcessDpiAwareness != nullptr) {
|
||||
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
// Ignore result, will fail if already called or manifest already specifies dpi awareness.
|
||||
@ -226,6 +228,8 @@ static void onkeyup(WPARAM w_param, LPARAM l_param) {
|
||||
}
|
||||
}
|
||||
|
||||
char fileName[256];
|
||||
|
||||
static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_param, LPARAM l_param) {
|
||||
SohImGui::EventImpl event_impl;
|
||||
event_impl.win32 = { h_wnd, static_cast<int>(message), static_cast<int>(w_param), static_cast<int>(l_param) };
|
||||
@ -265,6 +269,12 @@ static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_par
|
||||
case WM_KEYUP:
|
||||
onkeyup(w_param, l_param);
|
||||
break;
|
||||
case WM_DROPFILES:
|
||||
DragQueryFileA((HDROP)w_param, 0, fileName, 256);
|
||||
CVar_SetString("gDroppedFile", fileName);
|
||||
CVar_SetS32("gNewFileDropped", 1);
|
||||
Game::SaveSettings();
|
||||
break;
|
||||
case WM_SYSKEYDOWN:
|
||||
if ((w_param == VK_RETURN) && ((l_param & 1 << 30) == 0)) {
|
||||
toggle_borderless_window_full_screen(!dxgi.is_full_screen, true);
|
||||
@ -334,6 +344,8 @@ void gfx_dxgi_init(const char *game_name, bool start_in_fullscreen, uint32_t wid
|
||||
if (start_in_fullscreen) {
|
||||
toggle_borderless_window_full_screen(true, false);
|
||||
}
|
||||
|
||||
DragAcceptFiles(dxgi.h_wnd, TRUE);
|
||||
}
|
||||
|
||||
static void gfx_dxgi_set_fullscreen_changed_callback(void (*on_fullscreen_changed)(bool is_now_fullscreen)) {
|
||||
|
@ -81,7 +81,7 @@ static uint32_t frame_count;
|
||||
static vector<Framebuffer> framebuffers;
|
||||
static size_t current_framebuffer;
|
||||
static float current_noise_scale;
|
||||
static FilteringMode current_filter_mode = THREE_POINT;
|
||||
static FilteringMode current_filter_mode = FILTER_THREE_POINT;
|
||||
|
||||
GLuint pixel_depth_rb, pixel_depth_fb;
|
||||
size_t pixel_depth_rb_size;
|
||||
@ -376,7 +376,7 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
||||
append_line(fs_buf, &fs_len, "}");
|
||||
}
|
||||
|
||||
if (current_filter_mode == THREE_POINT) {
|
||||
if (current_filter_mode == FILTER_THREE_POINT) {
|
||||
#if __APPLE__
|
||||
append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture(tex, texCoord - (off)/texSize)");
|
||||
#else
|
||||
@ -638,6 +638,7 @@ static void gfx_opengl_select_texture(int tile, GLuint texture_id) {
|
||||
glActiveTexture(GL_TEXTURE0 + tile);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
}
|
||||
|
||||
static void gfx_opengl_upload_texture(const uint8_t *rgba32_buf, uint32_t width, uint32_t height) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba32_buf);
|
||||
}
|
||||
@ -657,7 +658,7 @@ static uint32_t gfx_cm_to_opengl(uint32_t val) {
|
||||
}
|
||||
|
||||
static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) {
|
||||
const GLint filter = linear_filter && current_filter_mode == LINEAR ? GL_LINEAR : GL_NEAREST;
|
||||
const GLint filter = linear_filter && current_filter_mode == FILTER_LINEAR ? GL_LINEAR : GL_NEAREST;
|
||||
glActiveTexture(GL_TEXTURE0 + tile);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
||||
|
@ -17,9 +17,9 @@ struct GfxClipParameters {
|
||||
};
|
||||
|
||||
enum FilteringMode {
|
||||
THREE_POINT,
|
||||
LINEAR,
|
||||
NONE
|
||||
FILTER_THREE_POINT,
|
||||
FILTER_LINEAR,
|
||||
FILTER_NONE
|
||||
};
|
||||
|
||||
// A hash function used to hash a: pair<float, float>
|
||||
|
@ -22,6 +22,7 @@
|
||||
#endif
|
||||
|
||||
#include "../../ImGuiImpl.h"
|
||||
#include "../../Cvar.h"
|
||||
|
||||
#include "gfx_window_manager_api.h"
|
||||
#include "gfx_screen_config.h"
|
||||
@ -29,6 +30,7 @@
|
||||
#include <WTypesbase.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include "../../GameSettings.h"
|
||||
|
||||
#define GFX_API_NAME "SDL2 - OpenGL"
|
||||
|
||||
@ -106,7 +108,7 @@ static void set_fullscreen(bool on, bool call_callback) {
|
||||
SDL_GetDesktopDisplayMode(0, &mode);
|
||||
window_width = mode.w;
|
||||
window_height = mode.h;
|
||||
SDL_ShowCursor(false);
|
||||
//SDL_ShowCursor(false);
|
||||
} else {
|
||||
window_width = DESIRED_SCREEN_WIDTH;
|
||||
window_height = DESIRED_SCREEN_HEIGHT;
|
||||
@ -133,6 +135,8 @@ static int target_fps = 60;
|
||||
static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen, uint32_t width, uint32_t height) {
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
@ -260,6 +264,11 @@ static void gfx_sdl_handle_events(void) {
|
||||
SDL_GL_GetDrawableSize(wnd, &window_width, &window_height);
|
||||
}
|
||||
break;
|
||||
case SDL_DROPFILE:
|
||||
CVar_SetString("gDroppedFile", event.drop.file);
|
||||
CVar_SetS32("gNewFileDropped", 1);
|
||||
Game::SaveSettings();
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
SDL_Quit(); // bandaid fix for linux window closing issue
|
||||
exit(0);
|
||||
|
@ -182,4 +182,4 @@ namespace Ship
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -448,6 +448,7 @@ u32 Actor_TextboxIsClosing(Actor* actor, GlobalContext* globalCtx);
|
||||
s8 func_8002F368(GlobalContext* globalCtx);
|
||||
void Actor_GetScreenPos(GlobalContext* globalCtx, Actor* actor, s16* x, s16* y);
|
||||
u32 Actor_HasParent(Actor* actor, GlobalContext* globalCtx);
|
||||
s32 GiveItemWithoutActor(GlobalContext* globalCtx, s32 getItemId);
|
||||
s32 func_8002F434(Actor* actor, GlobalContext* globalCtx, s32 getItemId, f32 xzRange, f32 yRange);
|
||||
void func_8002F554(Actor* actor, GlobalContext* globalCtx, s32 getItemId);
|
||||
void func_8002F580(Actor* actor, GlobalContext* globalCtx);
|
||||
|
@ -1293,6 +1293,7 @@ typedef struct {
|
||||
/* 0x1C9EC */ Vtx* keyboardVtx;
|
||||
/* 0x1C9F0 */ Vtx* nameEntryVtx;
|
||||
/* 0x1C9F4 */ u8 n64ddFlag;
|
||||
/* 0x1CA28 */ s16 n64ddFlags[3];
|
||||
/* 0x1CA38 */ s16 buttonIndex;
|
||||
/* 0x1CA3A */ s16 confirmButtonIndex; // 0: yes, 1: quit
|
||||
/* 0x1CA3C */ s16 menuMode;
|
||||
|
@ -289,6 +289,7 @@ typedef struct EnItem00 {
|
||||
/* 0x15A */ s16 unk_15A;
|
||||
/* 0x15C */ f32 scale;
|
||||
/* 0x160 */ ColliderCylinder collider;
|
||||
s16 ogParams;
|
||||
} EnItem00; // size = 0x1AC
|
||||
|
||||
// Only A_OBJ_SIGNPOST_OBLONG and A_OBJ_SIGNPOST_ARROW are used in room files.
|
||||
|
@ -211,9 +211,9 @@ typedef enum {
|
||||
/* 0x78 */ ITEM_MAGIC_SMALL,
|
||||
/* 0x79 */ ITEM_MAGIC_LARGE,
|
||||
/* 0x7A */ ITEM_HEART_PIECE_2,
|
||||
/* 0x7B */ ITEM_INVALID_1,
|
||||
/* 0x7C */ ITEM_INVALID_2,
|
||||
/* 0x7D */ ITEM_INVALID_3,
|
||||
/* 0x7B */ ITEM_SINGLE_MAGIC,
|
||||
/* 0x7C */ ITEM_DOUBLE_MAGIC,
|
||||
/* 0x7D */ ITEM_DOUBLE_DEFENSE,
|
||||
/* 0x7E */ ITEM_INVALID_4,
|
||||
/* 0x7F */ ITEM_INVALID_5,
|
||||
/* 0x80 */ ITEM_INVALID_6,
|
||||
@ -244,6 +244,15 @@ typedef enum {
|
||||
/* 0x99 */ ITEM_STICK_UPGRADE_30,
|
||||
/* 0x9A */ ITEM_NUT_UPGRADE_30,
|
||||
/* 0x9B */ ITEM_NUT_UPGRADE_40,
|
||||
/* 0x9C */ ITEM_BOTTLE_WITH_RED_POTION,
|
||||
/* 0x9D */ ITEM_BOTTLE_WITH_GREEN_POTION,
|
||||
/* 0x9E */ ITEM_BOTTLE_WITH_BLUE_POTION,
|
||||
/* 0x9F */ ITEM_BOTTLE_WITH_FAIRY,
|
||||
/* 0xA0 */ ITEM_BOTTLE_WITH_FISH,
|
||||
/* 0xA1 */ ITEM_BOTTLE_WITH_BLUE_FIRE,
|
||||
/* 0xA2 */ ITEM_BOTTLE_WITH_BUGS,
|
||||
/* 0xA3 */ ITEM_BOTTLE_WITH_POE,
|
||||
/* 0xA4 */ ITEM_BOTTLE_WITH_BIG_POE,
|
||||
/* 0xFC */ ITEM_LAST_USED = 0xFC,
|
||||
/* 0xFE */ ITEM_NONE_FE = 0xFE,
|
||||
/* 0xFF */ ITEM_NONE = 0xFF
|
||||
@ -380,7 +389,47 @@ typedef enum {
|
||||
/* 0x7B */ GI_BULLET_BAG_50,
|
||||
/* 0x7C */ GI_ICE_TRAP, // freezes link when opened from a chest
|
||||
/* 0x7D */ GI_TEXT_0, // no model appears over Link, shows text id 0 (pocket egg)
|
||||
/* 0x7E */ GI_MAX
|
||||
|
||||
/* 0x7E */ GI_MEDALLION_LIGHT,
|
||||
/* 0x7F */ GI_MEDALLION_FOREST,
|
||||
/* 0x80 */ GI_MEDALLION_FIRE,
|
||||
/* 0x81 */ GI_MEDALLION_WATER,
|
||||
/* 0x82 */ GI_MEDALLION_SHADOW,
|
||||
/* 0x83 */ GI_MEDALLION_SPIRIT,
|
||||
|
||||
/* 0x81 */ GI_STONE_KOKIRI,
|
||||
/* 0x82 */ GI_STONE_GORON,
|
||||
/* 0x83 */ GI_STONE_ZORA,
|
||||
|
||||
/* 0x81 */ GI_ZELDAS_LULLABY,
|
||||
/* 0x82 */ GI_SUNS_SONG,
|
||||
/* 0x83 */ GI_EPONAS_SONG,
|
||||
/* 0x81 */ GI_SONG_OF_STORMS,
|
||||
/* 0x82 */ GI_SONG_OF_TIME,
|
||||
/* 0x83 */ GI_SARIAS_SONG,
|
||||
|
||||
/* 0x81 */ GI_MINUET_OF_FOREST,
|
||||
/* 0x82 */ GI_BOLERO_OF_FIRE,
|
||||
/* 0x83 */ GI_SERENADE_OF_WATER,
|
||||
/* 0x81 */ GI_NOCTURNE_OF_SHADOW,
|
||||
/* 0x82 */ GI_REQUIEM_OF_SPIRIT,
|
||||
/* 0x83 */ GI_PRELUDE_OF_LIGHT,
|
||||
|
||||
GI_SINGLE_MAGIC,
|
||||
GI_DOUBLE_MAGIC,
|
||||
GI_DOUBLE_DEFENSE,
|
||||
|
||||
GI_BOTTLE_WITH_RED_POTION,
|
||||
GI_BOTTLE_WITH_GREEN_POTION,
|
||||
GI_BOTTLE_WITH_BLUE_POTION,
|
||||
GI_BOTTLE_WITH_FAIRY,
|
||||
GI_BOTTLE_WITH_FISH,
|
||||
GI_BOTTLE_WITH_BLUE_FIRE,
|
||||
GI_BOTTLE_WITH_BUGS,
|
||||
GI_BOTTLE_WITH_POE,
|
||||
GI_BOTTLE_WITH_BIG_POE,
|
||||
|
||||
/* 0x84 */ GI_MAX
|
||||
} GetItemID;
|
||||
|
||||
typedef enum {
|
||||
@ -501,7 +550,18 @@ typedef enum {
|
||||
/* 0x72 */ GID_BULLET_BAG_50,
|
||||
/* 0x73 */ GID_SWORD_KOKIRI,
|
||||
/* 0x74 */ GID_SKULL_TOKEN_2,
|
||||
/* 0x75 */ GID_MAXIMUM
|
||||
/* 0x74 */ GID_KOKIRI_EMERALD,
|
||||
/* 0x74 */ GID_GORON_RUBY,
|
||||
/* 0x74 */ GID_ZORA_SAPPHIRE,
|
||||
/* 0x75 */ GID_SONG_GENERIC,
|
||||
/* 0x76 */ GID_SONG_ZELDA,
|
||||
/* 0x77 */ GID_SONG_EPONA,
|
||||
/* 0x78 */ GID_SONG_SARIA,
|
||||
/* 0x79 */ GID_SONG_SUN,
|
||||
/* 0x7A */ GID_SONG_TIME,
|
||||
/* 0x7B */ GID_SONG_STORM,
|
||||
/* 0x7C */ GID_MAXIMUM
|
||||
|
||||
} GetItemDrawID;
|
||||
|
||||
typedef enum {
|
||||
|
@ -481,7 +481,7 @@ typedef struct Player {
|
||||
/* 0x042D */ s8 doorDirection;
|
||||
/* 0x042E */ s16 doorTimer;
|
||||
/* 0x0430 */ Actor* doorActor;
|
||||
/* 0x0434 */ s8 getItemId;
|
||||
/* 0x0434 */ s16 getItemId;
|
||||
/* 0x0436 */ u16 getItemDirection;
|
||||
/* 0x0438 */ Actor* interactRangeActor;
|
||||
/* 0x043C */ s8 mountSide;
|
||||
@ -614,4 +614,4 @@ typedef struct Player {
|
||||
/* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position
|
||||
} Player; // size = 0xA94
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "ultra64.h"
|
||||
#include "z64math.h"
|
||||
#include <randomizerTypes.h>
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ u8 buttonItems[8];
|
||||
@ -60,6 +61,21 @@ typedef struct {
|
||||
/* 0x24 */ s32 tempCollectFlags;
|
||||
} FaroresWindData; // size = 0x28
|
||||
|
||||
typedef struct {
|
||||
RandomizerCheck check;
|
||||
RandomizerGet get;
|
||||
} ItemLocationRando;
|
||||
|
||||
typedef struct {
|
||||
RandomizerCheck check;
|
||||
char hintText[200];
|
||||
} HintLocationRando;
|
||||
|
||||
typedef struct {
|
||||
RandomizerSettingKey key;
|
||||
u8 value;
|
||||
} RandoSetting;
|
||||
|
||||
typedef struct {
|
||||
/* 0x0000 */ s32 entranceIndex; // start of `save` substruct, originally called "memory"
|
||||
/* 0x0004 */ s32 linkAge; // 0: Adult; 1: Child
|
||||
@ -157,6 +173,17 @@ typedef struct {
|
||||
/* 0x1420 */ s16 worldMapArea;
|
||||
/* 0x1422 */ s16 sunsSongState; // controls the effects of suns song
|
||||
/* 0x1424 */ s16 healthAccumulator;
|
||||
RandoSetting randoSettings[300];
|
||||
ItemLocationRando itemLocations[500];
|
||||
HintLocationRando hintLocations[50];
|
||||
char childAltarText[250];
|
||||
char adultAltarText[750];
|
||||
char ganonHintText[150];
|
||||
char ganonText[250];
|
||||
u8 seedIcons[5];
|
||||
u8 dungeonsDone[8];
|
||||
u8 trialsDone[6];
|
||||
u8 temporaryWeapon;
|
||||
} SaveContext; // size = 0x1428
|
||||
|
||||
typedef enum {
|
||||
|
1000
soh/randomizerTypes.h
Normal file
1000
soh/randomizerTypes.h
Normal file
File diff suppressed because it is too large
Load Diff
19
soh/randomizer_generation.cpp
Normal file
19
soh/randomizer_generation.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include <Lib/spdlog/include/spdlog/spdlog.h>
|
||||
|
||||
void GenerateRandomizer() {
|
||||
int ret = Playthrough::Playthrough_Init(std::hash<std::string>{}(Settings::seed));
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret == -1) { // Failed to generate after 5 tries
|
||||
SPDLOG_ERROR(
|
||||
"\n\nFailed to generate after 5 tries.\nPress B to go back to the menu.\nA different seed might be "
|
||||
"successful.");
|
||||
return;
|
||||
} else {
|
||||
SPDLOG_ERROR("\n\nError %d with fill.\nPress Select to exit or B to go back to the menu.\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const auto& randomizerHash = GetRandomizerHash();
|
||||
}
|
@ -181,6 +181,61 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="soh\Enhancements\cosmetics\CosmeticsEditor.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\debugger\actorViewer.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\gfx.c" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\hint_list\hint_list_exclude_dungeon.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\hint_list\hint_list_exclude_overworld.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\hint_list\hint_list_item.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_castle_town.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_kakariko.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_shadow_temple.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_spirit_temple.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_forest_temple.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_gerudo_training_grounds.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_deku_tree.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_ice_cavern.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_fire_temple.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_lost_woods.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_bottom_of_the_well.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_hyrule_field.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_gerudo_valley.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_ganons_castle.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_water_temple.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_zoras_domain.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_jabujabus_belly.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_dodongos_cavern.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_death_mountain.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\cosmetics.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\custom_messages.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\debug.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\dungeon.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\entrance.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\fill.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\hints.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\hint_list.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\item.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\item_list.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\item_location.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\item_pool.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\logic.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\menu.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\music.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\patch.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\playthrough.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\preset.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\random.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\rando_main.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\settings.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\setting_descriptions.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\shops.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\sound_effects.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\spoiler_log.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\starting_inventory.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\tinyxml2.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\trial.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\utils.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\randomizer.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\randomizer_item_tracker.cpp" />
|
||||
<ClCompile Include="soh\frame_interpolation.cpp" />
|
||||
<ClCompile Include="soh\Enhancements\bootcommands.c" />
|
||||
<ClCompile Include="soh\Enhancements\debugconsole.cpp" />
|
||||
@ -890,6 +945,45 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="soh\Enhancements\cosmetics\CosmeticsEditor.h" />
|
||||
<ClInclude Include="soh\Enhancements\debugger\actorViewer.h" />
|
||||
<ClCompile Include="soh\Enhancements\randomizer\randomizer.h" />
|
||||
<ClInclude Include="soh\Enhancements\gfx.h" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\category.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\cosmetics.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\custom_messages.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\debug.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\dungeon.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\entrance.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\fill.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\hints.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\hint_list.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\item.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\item_list.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\item_location.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\item_pool.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\keys.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\location_access.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\logic.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\menu.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\music.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\patch.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\playthrough.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\pool_functions.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\preset.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\random.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\randomizer.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\rando_main.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\settings.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\setting_descriptions.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\shops.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\sound_effects.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\spoiler_log.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\starting_inventory.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\text.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\tinyxml2.h" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\trial.hpp" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\utils.hpp" />
|
||||
<ClInclude Include="randomizerTypes.h" />
|
||||
<ClInclude Include="soh\Enhancements\randomizer\randomizer_item_tracker.h" />
|
||||
<ClInclude Include="soh\frame_interpolation.h" />
|
||||
<ClInclude Include="include\alloca.h" />
|
||||
<ClInclude Include="include\bgm.h" />
|
||||
|
@ -2211,6 +2211,174 @@
|
||||
<ClCompile Include="soh\Enhancements\cosmetics\CosmeticsEditor.cpp">
|
||||
<Filter>Header Files\include</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\hint_list\hint_list_exclude_dungeon.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\hint_list\hint_list_exclude_overworld.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\hint_list\hint_list_item.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_bottom_of_the_well.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_castle_town.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_death_mountain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_deku_tree.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_dodongos_cavern.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_fire_temple.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_forest_temple.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_ganons_castle.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_gerudo_training_grounds.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_gerudo_valley.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_hyrule_field.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_ice_cavern.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_jabujabus_belly.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_kakariko.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_lost_woods.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_shadow_temple.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_spirit_temple.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_water_temple.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access\locacc_zoras_domain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\cosmetics.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\custom_messages.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\debug.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\dungeon.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\entrance.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\fill.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\hints.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\hint_list.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\item.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\item_list.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\item_location.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\item_pool.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\location_access.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\logic.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\menu.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\music.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\patch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\playthrough.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\preset.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\random.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\rando_main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\settings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\setting_descriptions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\shops.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\sound_effects.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\spoiler_log.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\starting_inventory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\tinyxml2.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\trial.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\3drando\utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\randomizer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\randomizer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\gfx.c">
|
||||
<Filter>Header Files\soh\Enhancements</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="soh\Enhancements\randomizer\randomizer_item_tracker.cpp">
|
||||
<Filter>Source Files\src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\overlays\actors\ovl_kaleido_scope\z_kaleido_scope.h">
|
||||
@ -3788,6 +3956,120 @@
|
||||
<ClInclude Include="soh\Enhancements\cosmetics\CosmeticsEditor.h">
|
||||
<Filter>Header Files\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\category.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\cosmetics.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\custom_messages.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\debug.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\dungeon.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\entrance.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\fill.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\hints.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\hint_list.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\item.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\item_list.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\item_location.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\item_pool.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\keys.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\location_access.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\logic.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\menu.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\music.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\patch.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\playthrough.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\pool_functions.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\preset.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\random.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\randomizer.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\rando_main.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\settings.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\setting_descriptions.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\shops.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\sound_effects.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\spoiler_log.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\starting_inventory.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\text.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\tinyxml2.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\trial.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\3drando\utils.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="randomizerTypes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\gfx.h">
|
||||
<Filter>Header Files\soh\Enhancements</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="soh\Enhancements\randomizer\randomizer_item_tracker.h">
|
||||
<Filter>Source Files\src</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="SHIPOFHARKINIAN.ico" />
|
||||
@ -3800,4 +4082,4 @@
|
||||
<ItemGroup>
|
||||
<None Include="include\macro.inc" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -130,6 +130,9 @@ std::map<uint32_t, ItemMapEntry> itemMapping = {
|
||||
ITEM_MAP_ENTRY(ITEM_COMPASS),
|
||||
ITEM_MAP_ENTRY(ITEM_DUNGEON_MAP),
|
||||
ITEM_MAP_ENTRY(ITEM_KEY_SMALL),
|
||||
ITEM_MAP_ENTRY(ITEM_HEART_CONTAINER),
|
||||
ITEM_MAP_ENTRY(ITEM_MAGIC_SMALL),
|
||||
ITEM_MAP_ENTRY(ITEM_MAGIC_LARGE)
|
||||
};
|
||||
|
||||
// Maps entries in the GS flag array to the area name it represents
|
||||
@ -196,6 +199,7 @@ std::map<uint32_t, QuestMapEntry> questMapping = {
|
||||
QUEST_MAP_ENTRY(QUEST_ZORA_SAPPHIRE, dgZoraSapphireIconTex),
|
||||
QUEST_MAP_ENTRY(QUEST_STONE_OF_AGONY, dgStoneOfAgonyIconTex),
|
||||
QUEST_MAP_ENTRY(QUEST_GERUDO_CARD, dgGerudosCardIconTex),
|
||||
QUEST_MAP_ENTRY(QUEST_SKULL_TOKEN, dgGoldSkulltulaIconTex),
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -212,12 +216,12 @@ typedef struct {
|
||||
|
||||
// Maps song ids to info for use in ImGui
|
||||
std::array<SongMapEntry, 12> songMapping = { {
|
||||
SONG_MAP_ENTRY(QUEST_SONG_LULLABY, 255, 255, 255),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_EPONA, 255, 255, 255),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_SARIA, 255, 255, 255),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_SUN, 255, 255, 255),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_TIME, 255, 255, 255),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_STORMS, 255, 255, 255),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_LULLABY, 224, 107, 255),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_EPONA, 255, 195, 60),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_SARIA, 127, 255, 137),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_SUN, 255, 255, 60),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_TIME, 119, 236, 255),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_STORMS, 165, 165, 165),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_MINUET, 150, 255, 100),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_BOLERO, 255, 80, 40),
|
||||
SONG_MAP_ENTRY(QUEST_SONG_SERENADE, 100, 150, 255),
|
||||
@ -226,6 +230,27 @@ std::array<SongMapEntry, 12> songMapping = { {
|
||||
SONG_MAP_ENTRY(QUEST_SONG_PRELUDE, 255, 240, 100),
|
||||
} };
|
||||
|
||||
#define VANILLA_SONG_MAP_ENTRY(id, r, g, b) \
|
||||
{ \
|
||||
id, #id "_Vanilla", #id "_Vanilla_Faded", ImVec4(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f) \
|
||||
}
|
||||
|
||||
// Maps song ids to info for use in ImGui
|
||||
std::array<SongMapEntry, 12> vanillaSongMapping = { {
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_LULLABY, 255, 255, 255),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_EPONA, 255, 255, 255),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_SARIA, 255, 255, 255),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_SUN, 255, 255, 255),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_TIME, 255, 255, 255),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_STORMS, 255, 255, 255),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_MINUET, 150, 255, 100),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_BOLERO, 255, 80, 40),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_SERENADE, 100, 150, 255),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_REQUIEM, 255, 160, 0),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_NOCTURNE, 255, 100, 255),
|
||||
VANILLA_SONG_MAP_ENTRY(QUEST_SONG_PRELUDE, 255, 240, 100),
|
||||
} };
|
||||
|
||||
// Encapsulates what is drawn by the passed-in function within a border
|
||||
template<typename T>
|
||||
void DrawGroupWithBorder(T&& drawFunc) {
|
||||
@ -1610,4 +1635,10 @@ void InitSaveEditor() {
|
||||
fadedCol.w = 0.3f;
|
||||
SohImGui::LoadResource(entry.nameFaded, gSongNoteTex, fadedCol);
|
||||
}
|
||||
for (const auto& entry : vanillaSongMapping) {
|
||||
SohImGui::LoadResource(entry.name, gSongNoteTex, entry.color);
|
||||
ImVec4 fadedCol = entry.color;
|
||||
fadedCol.w = 0.3f;
|
||||
SohImGui::LoadResource(entry.nameFaded, gSongNoteTex, fadedCol);
|
||||
}
|
||||
}
|
||||
|
63
soh/soh/Enhancements/gfx.c
Normal file
63
soh/soh/Enhancements/gfx.c
Normal file
@ -0,0 +1,63 @@
|
||||
#include "gfx.h"
|
||||
|
||||
#include "global.h"
|
||||
#include "z64.h"
|
||||
|
||||
extern GlobalContext* gGlobalCtx;
|
||||
|
||||
/**
|
||||
* Simple wrapper to load a texture to be drawn.
|
||||
*/
|
||||
void sprite_load(sprite_t* sprite) {
|
||||
OPEN_DISPS(gGlobalCtx->state.gfxCtx);
|
||||
|
||||
if (sprite->im_siz == G_IM_SIZ_16b) {
|
||||
gDPLoadTextureBlock(
|
||||
OVERLAY_DISP++,
|
||||
sprite->tex,
|
||||
sprite->im_fmt,
|
||||
G_IM_SIZ_16b, // @TEMP until I figure out how to use sprite->im_siz
|
||||
sprite->width, sprite->height,
|
||||
0,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP,
|
||||
G_TX_NOMASK, G_TX_NOMASK,
|
||||
G_TX_NOLOD, G_TX_NOLOD
|
||||
);
|
||||
} else {
|
||||
gDPLoadTextureBlock(
|
||||
OVERLAY_DISP++,
|
||||
sprite->tex,
|
||||
sprite->im_fmt,
|
||||
G_IM_SIZ_32b, // @TEMP until I figure out how to use sprite->im_siz
|
||||
sprite->width, sprite->height,
|
||||
0,
|
||||
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP,
|
||||
G_TX_NOMASK, G_TX_NOMASK,
|
||||
G_TX_NOLOD, G_TX_NOLOD
|
||||
);
|
||||
}
|
||||
|
||||
CLOSE_DISPS(gGlobalCtx->state.gfxCtx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple wrapper to draw a sprite/texture on the screen.
|
||||
* sprite_load needs to be ran right before this.
|
||||
*/
|
||||
void sprite_draw(sprite_t* sprite, int left, int top, int width, int height) {
|
||||
int width_factor = (1 << 10) * sprite->width / width;
|
||||
int height_factor = (1 << 10) * sprite->height / height;
|
||||
|
||||
OPEN_DISPS(gGlobalCtx->state.gfxCtx);
|
||||
|
||||
gSPWideTextureRectangle(
|
||||
OVERLAY_DISP++,
|
||||
OTRGetRectDimensionFromRightEdge(left) << 2, top << 2,
|
||||
(OTRGetRectDimensionFromRightEdge(left) + width) << 2, (top + height) << 2,
|
||||
G_TX_RENDERTILE,
|
||||
0, 0,
|
||||
width_factor, height_factor
|
||||
);
|
||||
|
||||
CLOSE_DISPS(gGlobalCtx->state.gfxCtx);
|
||||
}
|
17
soh/soh/Enhancements/gfx.h
Normal file
17
soh/soh/Enhancements/gfx.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef GFX_ENHANCEMENT_H
|
||||
#define GFX_EHHANCEMENT_H
|
||||
|
||||
#include "z64.h"
|
||||
|
||||
typedef struct {
|
||||
void *tex;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint8_t im_fmt;
|
||||
uint8_t im_siz;
|
||||
} sprite_t;
|
||||
|
||||
void sprite_load(sprite_t *sprite);
|
||||
void sprite_draw(sprite_t *sprite, int left, int top, int width, int height);
|
||||
|
||||
#endif
|
71
soh/soh/Enhancements/randomizer/3drando/category.hpp
Normal file
71
soh/soh/Enhancements/randomizer/3drando/category.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
|
||||
enum class Category {
|
||||
cNull,
|
||||
cKokiriForest,
|
||||
cForest,
|
||||
cGrotto,
|
||||
cMinigame,
|
||||
cChestMinigame,
|
||||
cLostWoods,
|
||||
cDekuScrub,
|
||||
cDekuScrubUpgrades,
|
||||
cNeedSpiritualStones,
|
||||
cSacredForestMeadow,
|
||||
cHyruleField,
|
||||
cLakeHylia,
|
||||
cGerudo,
|
||||
cGerudoValley,
|
||||
cGerudoFortress,
|
||||
cHauntedWasteland,
|
||||
cDesertColossus,
|
||||
cInnerMarket,
|
||||
cMarket,
|
||||
cHyruleCastle,
|
||||
cKakarikoVillage,
|
||||
cKakariko,
|
||||
cSkulltulaHouse,
|
||||
cGraveyard,
|
||||
cDeathMountainTrail,
|
||||
cDeathMountain,
|
||||
cGoronCity,
|
||||
cDeathMountainCrater,
|
||||
cZorasRiver,
|
||||
cZorasDomain,
|
||||
cZorasFountain,
|
||||
cLonLonRanch,
|
||||
cDekuTree,
|
||||
cDodongosCavern,
|
||||
cJabuJabusBelly,
|
||||
cForestTemple,
|
||||
cFireTemple,
|
||||
cWaterTemple,
|
||||
cSpiritTemple,
|
||||
cShadowTemple,
|
||||
cBottomOfTheWell,
|
||||
cIceCavern,
|
||||
cGerudoTrainingGrounds,
|
||||
cGanonsCastle,
|
||||
cSkulltula,
|
||||
cBossHeart,
|
||||
cTempleOfTime,
|
||||
cFairies,
|
||||
cOutsideGanonsCastle,
|
||||
cSong,
|
||||
cSongDungeonReward,
|
||||
cCow,
|
||||
cShop,
|
||||
cMerchant,
|
||||
cVanillaSmallKey,
|
||||
cVanillaGFSmallKey,
|
||||
cVanillaBossKey,
|
||||
cVanillaMap,
|
||||
cVanillaCompass,
|
||||
cAdultTrade,
|
||||
};
|
||||
|
||||
enum class OptionCategory {
|
||||
Setting,
|
||||
Cosmetic,
|
||||
Toggle,
|
||||
};
|
152
soh/soh/Enhancements/randomizer/3drando/cosmetics.cpp
Normal file
152
soh/soh/Enhancements/randomizer/3drando/cosmetics.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
#include "cosmetics.hpp"
|
||||
#include "random.hpp"
|
||||
#include <sstream>
|
||||
|
||||
namespace Cosmetics {
|
||||
|
||||
bool ValidHexString(std::string_view hexStr) {
|
||||
return hexStr.find_first_not_of("0123456789ABCDEFabcdef") == std::string_view::npos && hexStr.length() == 6;
|
||||
}
|
||||
|
||||
Color_RGBAf HexStrToColorRGBAf(const std::string& hexStr) {
|
||||
uint32_t hex = std::stoi(hexStr, nullptr, 16);
|
||||
|
||||
return Color_RGBAf{
|
||||
.r = ((hex & 0xFF0000) >> 16) / 255.0f,
|
||||
.g = ((hex & 0x00FF00) >> 8) / 255.0f,
|
||||
.b = (hex & 0x0000FF) / 255.0f,
|
||||
.a = 1.0f,
|
||||
};
|
||||
}
|
||||
|
||||
Color_RGBA8 HexStrToColorRGBA8(const std::string& hexStr) {
|
||||
uint32_t hex = std::stoi(hexStr, nullptr, 16);
|
||||
|
||||
return Color_RGBA8{
|
||||
.r = (uint8_t)((hex & 0xFF0000) >> 16),
|
||||
.g = (uint8_t)((hex & 0x00FF00) >> 8),
|
||||
.b = (uint8_t)(hex & 0x0000FF),
|
||||
.a = 0xFF,
|
||||
};
|
||||
}
|
||||
|
||||
std::string CustomColorOptionText(std::string_view color) {
|
||||
return std::string(CUSTOM_COLOR_STR.substr(0, CUSTOM_COLOR_STR.length() - 6)).append(color);
|
||||
}
|
||||
|
||||
std::string GetCustomColor(const std::string& str) {
|
||||
return str.substr(str.length() - 6);
|
||||
}
|
||||
|
||||
const std::array<std::string_view, 13> gauntletColors = {
|
||||
"FFFFFF", //Silver
|
||||
"FECF0F", //Gold
|
||||
"000006", //Black
|
||||
"025918", //Green
|
||||
"06025A", //Blue
|
||||
"600602", //Bronze
|
||||
"FF0000", //Red
|
||||
"025DB0", //Sky Blue
|
||||
"FA6A90", //Pink
|
||||
"FF00FF", //Magenta
|
||||
"D83A00", //Orange
|
||||
"5B8A06", //Lime
|
||||
"800080", //Purple
|
||||
};
|
||||
const std::array<std::string_view, 28> tunicColors = {
|
||||
"168A0E", //Kokiri Green
|
||||
"96000E", //Goron Red
|
||||
"002A8E", //Zora Blue
|
||||
"202020", //Black
|
||||
"FFFFFF", //White
|
||||
"FF4A0A", //Orange
|
||||
"86FF23", //Yellow
|
||||
"0094B0", //Cyan
|
||||
"362076", //Indigo
|
||||
"7B0080", //Purple
|
||||
"F04F7D", //Pink
|
||||
"323232", //Dark Gray
|
||||
"E44B4B", //Salmon
|
||||
"5A1A20", //Wine Red
|
||||
"7E705B", //Beige
|
||||
"583923", //Brown
|
||||
"72602B", //Sand
|
||||
"6b7E5D", //Tea Green
|
||||
"3C5800", //Dark Green
|
||||
"6CFFF8", //Powder Blue
|
||||
"005A4B", //Teal
|
||||
"0259FF", //Sky Blue
|
||||
"33405E", //Faded Blue
|
||||
"635AD2", //Lavender
|
||||
"9C1B4B", //Magenta
|
||||
"52314F", //Mauve
|
||||
"505A59", //Silver
|
||||
"F16F16", //Gold
|
||||
};
|
||||
const std::array<std::string_view, 20> naviInnerColors = {
|
||||
"FFFFFF", //White
|
||||
"00FF00", //Green
|
||||
"9696FF", //Light Blue
|
||||
"FFFF00", //Yellow
|
||||
"FF0000", //Red
|
||||
"FF00FF", //Magenta
|
||||
"FECC3C", //Gold
|
||||
"000000", //Black
|
||||
"FFFFFF", //Tatl
|
||||
"49146C", //Tael
|
||||
"2C9EC4", //Fi
|
||||
"E6DE83", //Ciela
|
||||
"D14902", //Epona
|
||||
"629C5F", //Ezlo
|
||||
"A83317", //KoRL
|
||||
"032660", //Linebeck
|
||||
"D62E31", //Loftwing
|
||||
"192426", //Midna
|
||||
"977A6C", //Phantom Zelda
|
||||
"FF0000", //Rainbow (starts at red)
|
||||
};
|
||||
const std::array<std::string_view, 20> naviOuterColors = {
|
||||
"0000FF", //White
|
||||
"00FF00", //Green
|
||||
"9696FF", //Light Blue
|
||||
"C89B00", //Yellow
|
||||
"FF0000", //Red
|
||||
"C8009B", //Magenta
|
||||
"FEC007", //Gold
|
||||
"000000", //Black
|
||||
"C89800", //Tatl
|
||||
"FF0000", //Tael
|
||||
"2C1983", //Fi
|
||||
"C6BE5B", //Ciela
|
||||
"551F08", //Epona
|
||||
"3F5D37", //Ezlo
|
||||
"DED7C5", //KoRL
|
||||
"EFFFFF", //Linebeck
|
||||
"FDE6CC", //Loftwing
|
||||
"D28330", //Midna
|
||||
"6F4667", //Phantom Zelda
|
||||
"FF0000", //Rainbow (starts at red)
|
||||
};
|
||||
const std::array<std::string_view, 13> weaponTrailColors = {
|
||||
"FFFFFF", //White
|
||||
"000000", //Black
|
||||
"FF0000", //Red
|
||||
"00FF00", //Green
|
||||
"0000FF", //Blue
|
||||
"FFFF00", //Yellow
|
||||
"00FFFF", //Cyan
|
||||
"FF00FF", //Magenta
|
||||
"FFA500", //Orange
|
||||
"FFD700", //Gold
|
||||
"800080", //Purple
|
||||
"FF69B4", //Pink
|
||||
"FF0000", //Rainbow (starts at red)
|
||||
};
|
||||
|
||||
//Generate random hex color
|
||||
std::string RandomColor() {
|
||||
std::ostringstream color;
|
||||
color << std::hex << (rand() % 0x1000000); //use default rand to not interfere with main settings
|
||||
return color.str();
|
||||
}
|
||||
} //namespace Cosmetics
|
50
soh/soh/Enhancements/randomizer/3drando/cosmetics.hpp
Normal file
50
soh/soh/Enhancements/randomizer/3drando/cosmetics.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Cosmetics {
|
||||
constexpr std::string_view RANDOM_CHOICE_STR = "Random Choice";
|
||||
constexpr std::string_view RANDOM_COLOR_STR = "Random Color";
|
||||
constexpr std::string_view CUSTOM_COLOR_STR = "Custom #FFFFFF";
|
||||
constexpr std::string_view CUSTOM_COLOR_PREFIX = "Custom #";
|
||||
|
||||
constexpr std::string_view RANDOM_CHOICE_DESC = "A random color from the list of colors will be\nchosen.";
|
||||
constexpr std::string_view RANDOM_COLOR_DESC = "A completely random color will be chosen.";
|
||||
constexpr std::string_view CUSTOM_COLOR_DESC = "Press A and type in a custom 6 digit hex color.";
|
||||
|
||||
enum CosmeticSettings {
|
||||
RANDOM_CHOICE,
|
||||
RANDOM_COLOR,
|
||||
CUSTOM_COLOR,
|
||||
NON_COLOR_COUNT,
|
||||
};
|
||||
|
||||
struct Color_RGBAf {
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
};
|
||||
|
||||
struct Color_RGBA8 {
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
};
|
||||
|
||||
extern const std::array<std::string_view, 13> gauntletColors;
|
||||
extern const std::array<std::string_view, 28> tunicColors;
|
||||
extern const std::array<std::string_view, 20> naviInnerColors;
|
||||
extern const std::array<std::string_view, 20> naviOuterColors;
|
||||
extern const std::array<std::string_view, 13> weaponTrailColors;
|
||||
|
||||
bool ValidHexString(std::string_view hexStr);
|
||||
Color_RGBAf HexStrToColorRGBAf(const std::string& hexStr);
|
||||
Color_RGBA8 HexStrToColorRGBA8(const std::string& hexStr);
|
||||
std::string CustomColorOptionText(std::string_view color);
|
||||
std::string GetCustomColor(const std::string& str);
|
||||
std::string RandomColor();
|
||||
} //namespace Cosmetics
|
495
soh/soh/Enhancements/randomizer/3drando/custom_messages.cpp
Normal file
495
soh/soh/Enhancements/randomizer/3drando/custom_messages.cpp
Normal file
@ -0,0 +1,495 @@
|
||||
#include "custom_messages.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "shops.hpp"
|
||||
#include "z64item.h"
|
||||
|
||||
#include <array>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
namespace CustomMessages {
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
class MessageEntryComp {
|
||||
public:
|
||||
bool operator()(const MessageEntry& lhs, const MessageEntry& rhs) const {
|
||||
return lhs.id < rhs.id;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr std::array EnglishDungeonNames = {
|
||||
"Deku Tree",
|
||||
"Dodongo's Cavern",
|
||||
"Jabu Jabu's Belly",
|
||||
"Forest Temple",
|
||||
"Fire Temple",
|
||||
"Water Temple",
|
||||
"Spirit Temple",
|
||||
"Shadow Temple",
|
||||
"Bottom of the Well",
|
||||
"Ice Cavern",
|
||||
"Ganon's Tower",
|
||||
"Gerudo Training Grounds",
|
||||
"Gerudo Fortress",
|
||||
"Ganon's Castle",
|
||||
};
|
||||
|
||||
constexpr std::array FrenchDungeonNames = {
|
||||
"Vénérable Arbre Mojo",
|
||||
"Caverne Dodongo",
|
||||
"Ventre de Jabu-Jabu",
|
||||
"Temple de la Forêt",
|
||||
"Temple du Feu",
|
||||
"Temple de l'Eau",
|
||||
"Temple de l'Esprit",
|
||||
"Temple de l'Ombre",
|
||||
"Puits",
|
||||
"Caverne Polaire",
|
||||
"Tour de Ganon",
|
||||
"Gymnase Gerudo",
|
||||
"Repaire des Voleurs",
|
||||
"Château de Ganon",
|
||||
};
|
||||
|
||||
constexpr std::array FrenchDungeonArticles = {
|
||||
"du ",
|
||||
"de la ",
|
||||
"du ",
|
||||
"du ",
|
||||
"du ",
|
||||
"du ",
|
||||
"du ",
|
||||
"du ",
|
||||
"du ",
|
||||
"de la ",
|
||||
"",
|
||||
"du ",
|
||||
"de la ",
|
||||
"du ",
|
||||
};
|
||||
|
||||
constexpr std::array SpanishDungeonNames = {
|
||||
"Gran Árbol Deku",
|
||||
"Cueva de los Dodongos",
|
||||
"Tripa de Jabu-Jabu",
|
||||
"Templo del Bosque",
|
||||
"Templo del Fuego",
|
||||
"Templo del Agua",
|
||||
"Templo del Espíritu",
|
||||
"Templo de las Sombras",
|
||||
"Fondo del pozo",
|
||||
"Caverna de hielo",
|
||||
"Torre de Ganon",
|
||||
"Centro de Instrucción Gerudo",
|
||||
"Fortaleza Gerudo",
|
||||
"Castillo de Ganon",
|
||||
};
|
||||
|
||||
constexpr std::array SpanishDungeonArticles = {
|
||||
"del",
|
||||
"de la",
|
||||
"de la",
|
||||
"del",
|
||||
"del",
|
||||
"del",
|
||||
"del",
|
||||
"del",
|
||||
"del",
|
||||
"de la",
|
||||
"de la",
|
||||
"del",
|
||||
"de la",
|
||||
"del",
|
||||
};
|
||||
|
||||
constexpr std::array DungeonColors = {
|
||||
QM_GREEN,
|
||||
QM_RED,
|
||||
QM_BLUE,
|
||||
QM_GREEN,
|
||||
QM_RED,
|
||||
QM_BLUE,
|
||||
QM_YELLOW,
|
||||
QM_PINK,
|
||||
QM_PINK,
|
||||
QM_LBLUE,
|
||||
QM_BLACK,
|
||||
QM_YELLOW,
|
||||
QM_YELLOW,
|
||||
QM_RED,
|
||||
};
|
||||
|
||||
std::set<MessageEntry, MessageEntryComp> messageEntries;
|
||||
std::vector<MessageEntry> arrangedMessageEntries;
|
||||
std::stringstream messageData;
|
||||
std::string arrangedMessageData;
|
||||
|
||||
//textBoxType and textBoxPosition are defined here: https://wiki.cloudmodding.com/oot/Text_Format#Message_Id
|
||||
void CreateMessage(uint32_t textId, uint32_t unk_04, uint32_t textBoxType, uint32_t textBoxPosition,
|
||||
std::string englishText, std::string frenchText, std::string spanishText) {
|
||||
MessageEntry newEntry = { textId, unk_04, textBoxType, textBoxPosition, { 0 } };
|
||||
|
||||
while ((englishText.size() % 4) != 0) {
|
||||
englishText += "\0"s;
|
||||
}
|
||||
messageData.seekg(0, messageData.end);
|
||||
newEntry.info[ENGLISH_U].offset = (char*)((int)messageData.tellg());
|
||||
newEntry.info[ENGLISH_U].length = englishText.size();
|
||||
messageData << englishText;
|
||||
|
||||
while ((frenchText.size() % 4) != 0) {
|
||||
frenchText += "\0"s;
|
||||
}
|
||||
messageData.seekg(0, messageData.end);
|
||||
newEntry.info[FRENCH_U].offset = (char*)((int)messageData.tellg());
|
||||
newEntry.info[FRENCH_U].length = frenchText.size();
|
||||
messageData << frenchText;
|
||||
|
||||
while ((spanishText.size() % 4) != 0) {
|
||||
spanishText += "\0"s;
|
||||
}
|
||||
messageData.seekg(0, messageData.end);
|
||||
newEntry.info[SPANISH_U].offset = (char*)((int)messageData.tellg());
|
||||
newEntry.info[SPANISH_U].length = spanishText.size();
|
||||
messageData << spanishText;
|
||||
|
||||
messageEntries.insert(newEntry);
|
||||
}
|
||||
|
||||
void CreateMessageFromTextObject(uint32_t textId, uint32_t unk_04, uint32_t textBoxType, uint32_t textBoxPosition, const Text& text) {
|
||||
CreateMessage(textId, unk_04, textBoxType, textBoxPosition, text.GetEnglish(), text.GetFrench(), text.GetSpanish());
|
||||
}
|
||||
|
||||
uint32_t NumMessages() {
|
||||
return messageEntries.size();
|
||||
}
|
||||
|
||||
std::pair<const char*, uint32_t> RawMessageEntryData() {
|
||||
arrangedMessageEntries.assign(messageEntries.begin(), messageEntries.end());
|
||||
const char* data = (const char*)arrangedMessageEntries.data();
|
||||
uint32_t size = arrangedMessageEntries.size() * sizeof(MessageEntry);
|
||||
return { data, size };
|
||||
}
|
||||
|
||||
std::pair<const char*, uint32_t> RawMessageData() {
|
||||
arrangedMessageData = messageData.str();
|
||||
const char* data = arrangedMessageData.data();
|
||||
uint32_t size = arrangedMessageData.size();
|
||||
return { data, size };
|
||||
}
|
||||
|
||||
void CreateAlwaysIncludedMessages() {
|
||||
// Bombchu (10) Purchase Prompt
|
||||
CreateMessage(0x8C, 0, 2, 3,
|
||||
INSTANT_TEXT_ON()+"Bombchu (10): 99 Rupees"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Buy"+NEWLINE()+"Don't buy"+COLOR(QM_WHITE)+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+"Bombchus (10): 99 rubis"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Acheter"+NEWLINE()+"Ne pas acheter"+COLOR(QM_WHITE)+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+"Bombchus (10): 99 rupias"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Comprar"+NEWLINE()+"No comprar"+COLOR(QM_WHITE)+MESSAGE_END());
|
||||
//Gold Skulltula Tokens (there are two text IDs the game uses)
|
||||
for (const uint32_t textId : {0xB4, 0xB5}) {
|
||||
CreateMessage(textId, 0, 2, 3,
|
||||
INSTANT_TEXT_ON()+"You destroyed a "+COLOR(QM_RED)+"Gold Skulltula"+COLOR(QM_WHITE)+". You got a"+NEWLINE()+"token proving you destroyed it!"+NEWLINE()+NEWLINE()+"You have "+COLOR(QM_RED)+SKULLTULAS_DESTROYED()+COLOR(QM_WHITE)+" tokens!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+"Vous venez de détruire une "+COLOR(QM_RED)+"Skulltula d'or"+COLOR(QM_WHITE)+"!"+NEWLINE()+"Ce symbole prouve votre prouesse!"+NEWLINE()+NEWLINE()+"Vous avez "+COLOR(QM_RED)+SKULLTULAS_DESTROYED()+COLOR(QM_WHITE)+" jetons!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+"¡Has eliminado una "+COLOR(QM_RED)+"skulltula dorada"+COLOR(QM_WHITE)+" y has"+NEWLINE()+"conseguido un símbolo para probarlo!"+NEWLINE()+NEWLINE()+"¡Tienes "+COLOR(QM_RED)+SKULLTULAS_DESTROYED()+COLOR(QM_WHITE)+" símbolos!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
|
||||
//Bombchu (10) Description
|
||||
CreateMessage(0xBC, 0, 2, 3,
|
||||
INSTANT_TEXT_ON()+COLOR(QM_RED)+"Bombchu (10): 99 Rupees"+NEWLINE()+COLOR(QM_WHITE)+"These look like toy mice, but they're"+NEWLINE()+"actually self-propelled time bombs!"+INSTANT_TEXT_OFF()+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+COLOR(QM_RED)+"Bombchus (10): 99 rubis"+NEWLINE()+COLOR(QM_WHITE)+"Profilée comme une souris mécanique, il"+NEWLINE()+"s'agit en fait d'une bombe à retardement"+NEWLINE()+"autopropulsée!"+INSTANT_TEXT_OFF()+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+COLOR(QM_RED)+"Bombchus (10): 99 rupias"+NEWLINE()+COLOR(QM_WHITE)+"Aunque parezcan ratoncitos de juguete,"+NEWLINE()+"¡son bombas de relojería autopropulsadas!"+INSTANT_TEXT_OFF()+SHOP_MESSAGE_BOX()+MESSAGE_END());
|
||||
//Boss Keys
|
||||
for (uint32_t bossKey = 0; bossKey <= (DUNGEON_SHADOW_TEMPLE - DUNGEON_FOREST_TEMPLE); bossKey++) {
|
||||
uint32_t dungeon = DUNGEON_FOREST_TEMPLE + bossKey;
|
||||
CreateMessage(0x9D4 + bossKey, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"You got the "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Boss Key"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"Vous trouvez la "+COLOR(DungeonColors[dungeon])+"Clé d'Or "+NEWLINE()+FrenchDungeonArticles[dungeon]+" "+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"¡Tienes la "+COLOR(DungeonColors[dungeon])+"gran llave "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
CreateMessage(0x9D9, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"You got the "+COLOR(DungeonColors[DUNGEON_GANONS_CASTLE_FIRST_PART])+EnglishDungeonNames[DUNGEON_GANONS_CASTLE_FIRST_PART]+NEWLINE()+"Boss Key"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"Vous trouvez la "+COLOR(DungeonColors[DUNGEON_GANONS_CASTLE_FIRST_PART])+"Clé d'Or "+NEWLINE()+FrenchDungeonArticles[DUNGEON_GANONS_CASTLE_FIRST_PART]+" "+FrenchDungeonNames[DUNGEON_GANONS_CASTLE_FIRST_PART]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"¡Tienes la "+COLOR(DungeonColors[DUNGEON_GANONS_CASTLE_FIRST_PART])+"gran llave "+SpanishDungeonArticles[DUNGEON_GANONS_CASTLE_FIRST_PART]+NEWLINE()+SpanishDungeonNames[DUNGEON_GANONS_CASTLE_FIRST_PART]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
//Compasses
|
||||
for (uint32_t dungeon = DUNGEON_DEKU_TREE; dungeon <= DUNGEON_ICE_CAVERN; dungeon++) {
|
||||
CreateMessage(0x9DA + dungeon, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_COMPASS)+INSTANT_TEXT_ON()+"You got the "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Compass"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_COMPASS)+INSTANT_TEXT_ON()+"Vous trouvez la "+COLOR(DungeonColors[dungeon])+"boussole "+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_COMPASS)+INSTANT_TEXT_ON()+"¡Tienes la "+COLOR(DungeonColors[dungeon])+"brújula "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
//Maps
|
||||
for (uint32_t dungeon = DUNGEON_DEKU_TREE; dungeon <= DUNGEON_ICE_CAVERN; dungeon++) {
|
||||
CreateMessage(0x9E4 + dungeon, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_DUNGEON_MAP)+INSTANT_TEXT_ON()+"You got the "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Map"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_DUNGEON_MAP)+INSTANT_TEXT_ON()+"Vous trouvez la "+COLOR(DungeonColors[dungeon])+"carte "+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_DUNGEON_MAP)+INSTANT_TEXT_ON()+"¡Has obtenido el "+COLOR(DungeonColors[dungeon])+"mapa "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
//Small Keys
|
||||
for (uint32_t smallKey = 0; smallKey <= (DUNGEON_BOTTOM_OF_THE_WELL - DUNGEON_FOREST_TEMPLE); smallKey++) {
|
||||
uint32_t dungeon = DUNGEON_FOREST_TEMPLE + smallKey;
|
||||
CreateMessage(0x9EE + smallKey, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got a "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Small Key"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez une "+COLOR(DungeonColors[dungeon])+"Petite Clé"+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido una "+COLOR(DungeonColors[dungeon])+"llave pequeña "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
for (uint32_t smallKey = 0; smallKey <= (DUNGEON_GANONS_CASTLE_FIRST_PART - DUNGEON_GERUDO_TRAINING_GROUNDS); smallKey++) {
|
||||
uint32_t dungeon = DUNGEON_GERUDO_TRAINING_GROUNDS + smallKey;
|
||||
CreateMessage(0x9F4 + smallKey, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got a "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Small Key"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez une "+COLOR(DungeonColors[dungeon])+"Petite Clé"+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido una "+COLOR(DungeonColors[dungeon])+"llave pequeña "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
//Key Rings
|
||||
for (uint32_t smallKey = 0; smallKey <= (DUNGEON_BOTTOM_OF_THE_WELL - DUNGEON_FOREST_TEMPLE); smallKey++) {
|
||||
uint32_t dungeon = DUNGEON_FOREST_TEMPLE + smallKey;
|
||||
CreateMessage(0x9300 + smallKey, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got a "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Key Ring"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez un "+COLOR(DungeonColors[dungeon])+"trousseau"+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido un "+COLOR(DungeonColors[dungeon])+"llavero "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
for (uint32_t smallKey = 0; smallKey <= (DUNGEON_GANONS_CASTLE_FIRST_PART - DUNGEON_GERUDO_TRAINING_GROUNDS); smallKey++) {
|
||||
uint32_t dungeon = DUNGEON_GERUDO_TRAINING_GROUNDS + smallKey;
|
||||
CreateMessage(0x9306 + smallKey, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got a "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Key Ring"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez un "+COLOR(DungeonColors[dungeon])+"trousseau"+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido un "+COLOR(DungeonColors[dungeon])+"llavero "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
//Tycoon's Wallet
|
||||
CreateMessage(0x09F7, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_WALLET_GIANT)+INSTANT_TEXT_ON()+"You got a "+COLOR(QM_RED)+"Tycoon's Wallet"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+NEWLINE()+"It's gigantic! Now you can carry"+NEWLINE()+"up to "+COLOR(QM_YELLOW)+"999 "+COLOR(QM_WHITE)+COLOR(QM_YELLOW)+"Rupees"+COLOR(QM_WHITE)+"!"+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_WALLET_GIANT)+INSTANT_TEXT_ON()+"Vous obtenez la "+COLOR(QM_RED)+"Bourse de star"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+NEWLINE()+"Elle peut contenir jusqu'à "+COLOR(QM_YELLOW)+"999 "+COLOR(QM_WHITE)+COLOR(QM_YELLOW)+"rubis"+COLOR(QM_WHITE)+"!"+NEWLINE()+"C'est gigantesque!"+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_WALLET_GIANT)+INSTANT_TEXT_ON()+"¡Has conseguido una "+COLOR(QM_RED)+"bolsa para ricachones"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+NEWLINE()+"¡Qué descomunal! Ya puedes llevar"+NEWLINE()+"hasta "+COLOR(QM_YELLOW)+"999 "+COLOR(QM_WHITE)+COLOR(QM_YELLOW)+"rupias"+COLOR(QM_WHITE)+"!"+MESSAGE_END());
|
||||
//Saria's Song Default Hint
|
||||
CreateMessage(0x0A00, 0, 2, 3,
|
||||
UNSKIPPABLE()+"Have you tried talking to the gossip"+NEWLINE()+ "stones around Hyrule? They might have"+NEWLINE()+"some good advice... Hee hee!"+WAIT_FOR_INPUT()+"If you learn something from the gossip stones,"+NEWLINE()+"I will remember it!"+EVENT_TRIGGER()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+"As-tu parlé aux pierres à potins"+NEWLINE()+ "dans Hyrule? Elles sont de bons conseils..."+NEWLINE()+"Hi hi!"+WAIT_FOR_INPUT()+"Si elles te révèlent quelque chose,"+NEWLINE()+"je m'en souviendrai!"+EVENT_TRIGGER()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+"¿Has probado a consultarle a las"+NEWLINE()+ "piedras chismosas esparcidas por Hyrule? Puede"+NEWLINE()+"que sean de ayuda a tu empresa... ¡Ji, ji!"+WAIT_FOR_INPUT()+"¡Puedo recordarte todo lo que aprendas de ellas,"+NEWLINE()+"si así lo deseas!"+EVENT_TRIGGER()+MESSAGE_END());
|
||||
//Poe Collector (when enough has been sold)
|
||||
CreateMessage(0x70F8, 0, 0, 0,
|
||||
UNSKIPPABLE()+"Wait a minute! WOW!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"You have earned enough points!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Young man, you are a genuine "+COLOR(QM_RED)+"ghost hunter"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"Is that what you expected me to say?"+NEWLINE()+"Heh heh heh!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Because of you, I have extra inventory of"+NEWLINE()+COLOR(QM_RED)+"Big Poes"+COLOR(QM_WHITE)+", so this will be the last time I can"+NEWLINE()
|
||||
+"buy one of these ghosts."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"You're thinking about what I promised would"+NEWLINE()+"happen when you earned enough points."+NEWLINE()+"Heh heh."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"Don't worry. I didn't forget. Just take this."+MESSAGE_END(),
|
||||
UNSKIPPABLE()+"Ooooh! WHOA!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Tu as obtenu suffisamment de points!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Tu es un véritable "+COLOR(QM_RED)+"chasseur de fantômes"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"Il est content, hein?"+NEWLINE()+"Il est content le monsieur?"+NEWLINE()+"Hé hé hé!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Grâce à toi, mon stock d'"+COLOR(QM_RED)+"Âmes"+COLOR(QM_WHITE)+" est plein!"+NEWLINE()+"C'est donc la dernière fois que nous"+NEWLINE()+"faisons affaire."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"Je sais, je sais..."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Nous avions passé un pacte..."+NEWLINE()+"Tu as eu tes points et je t'en félicite..."+NEWLINE()+"Hé hé hé!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"Alors prends donc ceci, mon bon ami!"+MESSAGE_END(),
|
||||
UNSKIPPABLE()+"¡Un momento! ¡OYE!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¡Has conseguido los puntos suficientes!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¡Jovencito, eres un auténtico "+COLOR(QM_RED)+"cazador de"+NEWLINE()+"fantasmas"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"¿Era eso lo que esperabas que dijera?"+NEWLINE()+"¡Je, je je!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Gracias a ti, ya tengo la cantidad necesaria"+NEWLINE()+"de "+COLOR(QM_RED)+"grandes poes"+COLOR(QM_WHITE)+", así que esta será la"+NEWLINE()
|
||||
+"última vez que te compre unos de ese tipo."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¿Recuerdas lo que te dije que ocurriría"+NEWLINE()+"cuando tuvieses suficientes puntos?"+NEWLINE()+"Je, je, je."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"Tranquilo, que no se me ha olvidado."+NEWLINE()+"Toma esto."+MESSAGE_END());
|
||||
//Ice Trap
|
||||
CreateMessage(0x9002, 0, 2, 3,
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+COLOR(QM_RED)+"FOOL!"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+COLOR(QM_RED)+"IDIOT!"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+COLOR(QM_RED)+"¡TONTO!"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
//Business Scrubs
|
||||
//The less significant byte represents the price of the item
|
||||
for (uint32_t price = 0; price <= 95; price += 5) {
|
||||
CreateMessage(0x9000 + price, 0, 0, 0,
|
||||
INSTANT_TEXT_ON()+"I'll sell you something good for "+COLOR(QM_RED)+std::to_string(price)+" Rupees"+COLOR(QM_WHITE)+"!"+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"OK"+NEWLINE()+"No way"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+"Je te vends un truc super pour "+COLOR(QM_RED)+std::to_string(price)+" Rubis"+COLOR(QM_WHITE)+"!"+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"D'accord"+NEWLINE()+"Hors de question"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+"¡Te puedo vender algo bueno por "+COLOR(QM_RED)+std::to_string(price)+" rupias"+COLOR(QM_WHITE)+"!"+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Vale"+NEWLINE()+"Ni hablar"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
//Poe Collector
|
||||
//The last digit represent the number of poes needed to collect
|
||||
for (uint32_t poes = 1; poes <= 10; poes++) {
|
||||
CreateMessage(0x9080 + poes, 0, 0, 0,
|
||||
UNSKIPPABLE()+"Oh, you brought a Poe today!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Hmmmm!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Very interesting! This is a "+COLOR(QM_RED)+"Big Poe"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"I'll buy it for "+COLOR(QM_RED)+"50 Rupees"+COLOR(QM_WHITE)+"."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"On top of that, I'll put "+COLOR(QM_RED)+"100 points "+COLOR(QM_WHITE)+"on"+NEWLINE()+"your card."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"If you earn "+COLOR(QM_RED)+std::to_string(poes * 100)+" points"+COLOR(QM_WHITE)+", you'll be a"+NEWLINE()+"happy man! Heh heh."+MESSAGE_END(),
|
||||
|
||||
UNSKIPPABLE()+"Oh! Tu as apporté un fantôme!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Hmmmm!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Magnifique!"+NEWLINE()+"C'est une "+COLOR(QM_RED)+"Âme"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"Je t'en donne "+COLOR(QM_RED)+"50 Rubis"+COLOR(QM_WHITE)+"."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Et en plus, j'inscris "+COLOR(QM_RED)+"100 points "+COLOR(QM_WHITE)+NEWLINE()+"sur ta carte."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"Obtiens "+COLOR(QM_RED)+std::to_string(poes * 100)+" points"+COLOR(QM_WHITE)+" et tu ne"+NEWLINE()+"seras pas déçu..."+NEWLINE()+"Hé hé hé."+MESSAGE_END(),
|
||||
|
||||
UNSKIPPABLE()+"¡Vaya! ¡Traes un poe!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¡Mmm! ¿A ver?"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¡Qué interesante! ¡Es un "+COLOR(QM_RED)+"gran poe"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"Te daré "+COLOR(QM_RED)+"50 rupias "+COLOR(QM_WHITE)+"por él."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Y además agregaré "+COLOR(QM_RED)+"100 puntos "+COLOR(QM_WHITE)+"a tu"+NEWLINE()+"tarjeta."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
||||
+"¡Si llegas a "+COLOR(QM_RED)+std::to_string(poes * 100)+" puntos"+COLOR(QM_WHITE)+", serás muy feliz!"+NEWLINE()+"Je, je, je..."+MESSAGE_END());
|
||||
}
|
||||
|
||||
//Talon (this is to prevent accidentally skipping Malon in HC)
|
||||
CreateMessage(0x9100, 0, 2, 0,
|
||||
UNSKIPPABLE()+"You should go talk to my daughter Malon,"+NEWLINE()+"she has an item for you."+NEWLINE()+SET_SPEED(3)+"........."+SET_SPEED(0)+WAIT_FOR_INPUT()+"I have to think about some stuff now,"+NEWLINE()+"please don't distract me."+MESSAGE_END(),
|
||||
UNSKIPPABLE()+"Zzzz... Muh... Malon..."+NEWLINE()+"Parler avec... Malon..."+NEWLINE()+SET_SPEED(3)+"........."+SET_SPEED(0)+WAIT_FOR_INPUT()+"Si fatigué..."+NEWLINE()+"Quelle vie..."+MESSAGE_END(),
|
||||
UNSKIPPABLE()+"Habla con Malon, tiene algo que darte..."+SET_SPEED(3)+"........."+SET_SPEED(0)+MESSAGE_END());
|
||||
|
||||
//Bow Shooting Gallery reminder
|
||||
CreateMessage(0x9140, 0, 0, 0,
|
||||
UNSKIPPABLE()+"Wonderful! Bravo! Perfect!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Here's a fantastic present! But I have"+COLOR(QM_RED)+NEWLINE()+"something else "+COLOR(QM_WHITE)+"for you once you have a bow."+SET_SPEED(30)+" "+EVENT_TRIGGER()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+"Merveilleux! Bravo! C'est parfait!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Voici un prix fantastique! J'aurai "+COLOR(QM_RED)+"autre chose"+COLOR(QM_WHITE)+NEWLINE()+"pour toi quand tu auras un arc."+SET_SPEED(30)+" "+EVENT_TRIGGER()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+"¡Espectacular! ¡Bravo! ¡Perfecto!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¡Toma este sensacional regalo! Pero te tengo"+NEWLINE()+"guardado "+COLOR(QM_RED)+"algo más "+COLOR(QM_WHITE)+"para cuando traigas tu"+NEWLINE()+"propio arco."+SET_SPEED(30)+" "+EVENT_TRIGGER()+MESSAGE_END());
|
||||
|
||||
//Shopsanity items
|
||||
//64 textboxes, 2 for each of 32 potential shopsanity items
|
||||
for(uint32_t shopitems = 0; shopitems < NonShopItems.size(); shopitems++) {
|
||||
Text name = NonShopItems[shopitems].Name;
|
||||
std::string price = std::to_string(NonShopItems[shopitems].Price);
|
||||
//Prevent names from being too long and overflowing textbox
|
||||
if (name.GetEnglish() == "Piece of Heart (Treasure Chest Minigame)") {
|
||||
name = Text{"Piece of Heart", "Quart de Coeur", "Pieza de corazón"};
|
||||
} else if (name.GetEnglish() == "Green Rupee (Treasure Chest Minigame)") {
|
||||
name = Text{"Green Rupee", "Rubis Vert", "Rupia verde"};
|
||||
}
|
||||
//Message to display when hovering over the item
|
||||
if (NonShopItems[shopitems].Repurchaseable) { //Different checkbox for repurchaseable items
|
||||
CreateMessage(0x9200+shopitems*2, 0, 0, 0,
|
||||
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetEnglish()+": "+price+" Rupees"+NEWLINE()+COLOR(QM_WHITE)+"Special deal!"+NEWLINE()+"Buy as many as you want!"+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetFrench()+": "+price+" rubis"+NEWLINE()+COLOR(QM_WHITE)+"Offre spéciale!"+NEWLINE()+"Achetez-en à volonté!"+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetSpanish()+": "+price+" rupias"+NEWLINE()+COLOR(QM_WHITE)+"¡Oferta especial!"+NEWLINE()+"¡Compra todo lo que quieras!"+SHOP_MESSAGE_BOX()+MESSAGE_END());
|
||||
}
|
||||
else { //Normal textbox
|
||||
CreateMessage(0x9200+shopitems*2, 0, 0, 0,
|
||||
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetEnglish()+": "+price+" Rupees"+NEWLINE()+COLOR(QM_WHITE)+"Special deal! ONE LEFT!"+NEWLINE()+"Get it while it lasts!"+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetFrench()+": "+price+" rubis"+NEWLINE()+COLOR(QM_WHITE)+"Offre spéciale! DERNIER EN STOCK!"+NEWLINE()+"Faites vite!"+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetSpanish()+": "+price+" rupias"+NEWLINE()+COLOR(QM_WHITE)+"¡Oferta especial! ¡SOLO QUEDA UNA UNIDAD!"+NEWLINE()+"¡Hazte con ella antes de que se agote!"+SHOP_MESSAGE_BOX()+MESSAGE_END());
|
||||
}
|
||||
//Message to display when going to buy the item
|
||||
CreateMessage(0x9200+shopitems*2+1, 0, 0, 0,
|
||||
INSTANT_TEXT_ON()+name.GetEnglish()+": "+price+" Rupees"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Buy"+NEWLINE()+"Don't buy"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+name.GetFrench()+": "+price+" rubis"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Acheter"+NEWLINE()+"Ne pas acheter"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
INSTANT_TEXT_ON()+name.GetSpanish()+": "+price+" rupias"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Comprar"+NEWLINE()+"No comprar"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
//easter egg
|
||||
CreateMessage(0x96F, 0, 2, 2,
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Oh hey, you watched all the credits!"+NEWLINE()+CENTER_TEXT()+"Here's a prize for your patience."+NEWLINE()+CENTER_TEXT()+"Unlocking MQ and saving..."+NEWLINE()+NEWLINE()+CENTER_TEXT()+COLOR(QM_RED)+"Do not remove the Game Card"+NEWLINE()+CENTER_TEXT()+"or turn the power off."+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"The Legend of Zelda Ocarina of Time 3D"+NEWLINE()+CENTER_TEXT()+"Master Quest va être déverrouillé."+NEWLINE()+CENTER_TEXT()+"Sauvegarde... Veuillez patienter."+NEWLINE()+NEWLINE()+CENTER_TEXT()+COLOR(QM_RED)+"N'éteignez pas la console et"+NEWLINE()+CENTER_TEXT()+"ne retirez pas la carte de jeu"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Desbloqueando The Legend of Zelda"+NEWLINE()+CENTER_TEXT()+"Ocarina of Time 3D Master Quest."+NEWLINE()+CENTER_TEXT()+"Guardando. Espera un momento..."+NEWLINE()+NEWLINE()+CENTER_TEXT()+COLOR(QM_RED)+"No saques la tarjeta de juego"+NEWLINE()+CENTER_TEXT()+"ni apagues la consola."+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
CreateMessage(0x970, 0, 2, 3,
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Master Quest doesn't affect the Randomizer,"+NEWLINE()+CENTER_TEXT()+"so you can use 3 more save slots now."+NEWLINE()+NEWLINE()+CENTER_TEXT()+"Thanks for playing!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Vous pouvez désormais jouer à"+NEWLINE()+CENTER_TEXT()+"The Legend of Zelda Ocarina of Time 3D"+NEWLINE()+CENTER_TEXT()+"Master Quest!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"¡Ya puedes jugar The Legend of Zelda"+NEWLINE()+CENTER_TEXT()+"Ocarina of Time 3D Master Quest!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
|
||||
//Messages for the new Lake Hylia switch
|
||||
CreateMessage(0x346, 0, 1, 3,
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Water level control system."+NEWLINE()+CENTER_TEXT()+"Keep away!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Contrôle du niveau d'eau."+NEWLINE()+CENTER_TEXT()+"Ne pas toucher!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Control del nivel del agua."+NEWLINE()+CENTER_TEXT()+"¡No te acerques!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
CreateMessage(0x1B3, 0, 0, 3,
|
||||
UNSKIPPABLE()+"This switch is rustier than you think."+WAIT_FOR_INPUT()+"Something must be wrong with the pipe"+NEWLINE()+"system in the Water Temple."+MESSAGE_END(),
|
||||
UNSKIPPABLE()+"Cet interrupteur est très rouillé."+WAIT_FOR_INPUT()+"Quelque chose ne va pas avec"+NEWLINE()+"la tuyauterie du Temple de l'Eau."+MESSAGE_END(),
|
||||
UNSKIPPABLE()+"El interruptor está más oxidado de lo que"+NEWLINE()+"aparenta."+WAIT_FOR_INPUT()+"Algo debe andar mal en el sistema de"+NEWLINE()+"cañerías del Templo del Agua."+MESSAGE_END());
|
||||
|
||||
//Treasure chest shop keys. If they're not randomized leave the base game text
|
||||
if (Settings::ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS)) {
|
||||
CreateMessage(0x0F3, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got a "+COLOR(QM_RED)+"Treasure Chest Shop"+NEWLINE()+"Small Key"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez une "+COLOR(QM_RED)+"Petite Clé"+NEWLINE()+"de la Chasse-aux-Trésors"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido una "+COLOR(QM_RED)+"llave pequeña del"+NEWLINE()+"Cofre del Tesoro"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
} else if (Settings::ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK)) {
|
||||
CreateMessage(0x0F3, 0, 2, 3,
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got all 6 "+COLOR(QM_RED)+"Treasure Chest Shop"+NEWLINE()+"Small Keys"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez les "+COLOR(QM_RED)+"petites clés"+NEWLINE()+"de la Chasse-aux-Trésors"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
||||
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido todas las 6 "+COLOR(QM_RED)+"llaves"+NEWLINE()+"pequeñas del Cofre del Tesoro"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
||||
}
|
||||
}
|
||||
|
||||
Text AddColorsAndFormat(Text text, const std::vector<uint8_t>& colors /*= {}*/) {
|
||||
|
||||
//for each language
|
||||
for (std::string* textStr : {&text.english, &text.french, &text.spanish}) {
|
||||
|
||||
//insert playername
|
||||
size_t atSymbol = textStr->find('@');
|
||||
while (atSymbol != std::string::npos) {
|
||||
textStr->replace(atSymbol, 1, PLAYER_NAME());
|
||||
atSymbol = textStr->find('@');
|
||||
}
|
||||
//insert newlines either manually or when encountering a '&'
|
||||
constexpr size_t lineLength = 44;
|
||||
size_t lastNewline = 0;
|
||||
while (lastNewline + lineLength < textStr->length()) {
|
||||
size_t carrot = textStr->find('^', lastNewline);
|
||||
size_t ampersand = textStr->find('&', lastNewline);
|
||||
size_t lastSpace = textStr->rfind(' ', lastNewline + lineLength);
|
||||
size_t lastPeriod = textStr->rfind('.', lastNewline + lineLength);
|
||||
//replace '&' first if it's within the newline range
|
||||
if (ampersand < lastNewline + lineLength) {
|
||||
textStr->replace(ampersand, 1, NEWLINE());
|
||||
lastNewline = ampersand + NEWLINE().length();
|
||||
//or move the lastNewline cursor to the next line if a '^' is encountered
|
||||
} else if (carrot < lastNewline + lineLength) {
|
||||
lastNewline = carrot + 1;
|
||||
//some lines need to be split but don't have spaces, look for periods instead
|
||||
} else if (lastSpace == std::string::npos) {
|
||||
textStr->replace(lastPeriod, 1, "."+NEWLINE());
|
||||
lastNewline = lastPeriod + NEWLINE().length() + 1;
|
||||
} else {
|
||||
textStr->replace(lastSpace, 1, NEWLINE());
|
||||
lastNewline = lastSpace + NEWLINE().length();
|
||||
}
|
||||
}
|
||||
//clean up any remaining '&' characters
|
||||
size_t ampersand = textStr->find('&');
|
||||
while (ampersand != std::string::npos) {
|
||||
textStr->replace(ampersand, 1, NEWLINE());
|
||||
ampersand = textStr->find('&');
|
||||
}
|
||||
|
||||
//insert box break
|
||||
size_t carrotSymbol = textStr->find('^');
|
||||
while (carrotSymbol != std::string::npos) {
|
||||
textStr->replace(carrotSymbol, 1, INSTANT_TEXT_OFF()+WAIT_FOR_INPUT()+INSTANT_TEXT_ON());
|
||||
carrotSymbol = textStr->find('^');
|
||||
}
|
||||
//add colors
|
||||
for (auto color : colors) {
|
||||
size_t firstHashtag = textStr->find('#');
|
||||
if (firstHashtag != std::string::npos) {
|
||||
textStr->replace(firstHashtag, 1, COLOR(color));
|
||||
size_t secondHashtag = textStr->find('#');
|
||||
if (secondHashtag == std::string::npos) {
|
||||
CitraPrint("ERROR: Couldn't find second '#' in " + (*textStr));
|
||||
} else {
|
||||
textStr->replace(secondHashtag, 1, COLOR(QM_WHITE));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Text{"","",""}+UNSKIPPABLE()+INSTANT_TEXT_ON()+text+INSTANT_TEXT_OFF()+MESSAGE_END();
|
||||
}
|
||||
|
||||
void ClearMessages() {
|
||||
messageEntries.clear();
|
||||
arrangedMessageEntries.clear();
|
||||
messageData.str("");
|
||||
arrangedMessageData = "";
|
||||
}
|
||||
|
||||
std::string MESSAGE_END() { return "\x7F\x00"s; }
|
||||
std::string WAIT_FOR_INPUT() { return "\x7F\x01"s; }
|
||||
std::string HORIZONTAL_SPACE(uint8_t x) {
|
||||
return "\x7F\x02"s + char(x);
|
||||
}
|
||||
std::string GO_TO(uint16_t x) {
|
||||
return "\x7F\x03"s + char(x >> 8) + char(x & 0x00FF);
|
||||
}
|
||||
std::string INSTANT_TEXT_ON() { return "\x7F\x04"s; }
|
||||
std::string INSTANT_TEXT_OFF() { return "\x7F\x05"s; }
|
||||
std::string SHOP_MESSAGE_BOX() { return "\x7F\x06\x00"s; }
|
||||
std::string EVENT_TRIGGER() { return "\x7F\x07"s; }
|
||||
std::string DELAY_FRAMES(uint8_t x) {
|
||||
return "\x7F\x08"s + char(x);
|
||||
}
|
||||
std::string CLOSE_AFTER(uint8_t x) {
|
||||
return "\x7F\x0A"s + char(x);
|
||||
}
|
||||
std::string PLAYER_NAME() { return "\x7F\x0B"s; }
|
||||
std::string PLAY_OCARINA() { return "\x7F\x0C"s; }
|
||||
std::string ITEM_OBTAINED(uint8_t x) {
|
||||
return "\x7F\x0F"s + char(x);
|
||||
}
|
||||
std::string SET_SPEED(uint8_t x) {
|
||||
return "\x7F\x10"s + char(x);
|
||||
}
|
||||
std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"s; }
|
||||
std::string CURRENT_TIME() { return "\x7F\x17"s; }
|
||||
std::string UNSKIPPABLE() { return "\x7F\x19"s; }
|
||||
std::string TWO_WAY_CHOICE() { return "\x7F\x1A\xFF\xFF\xFF\xFF"s; }
|
||||
std::string NEWLINE() { return "\x7F\x1C"s; }
|
||||
std::string COLOR(uint8_t x) { return "\x7F\x1D"s + char(x); }
|
||||
std::string CENTER_TEXT() { return "\x7F\x1E"s; }
|
||||
std::string IF_NOT_MQ() { return "\x7F\x29"s; }
|
||||
std::string MQ_ELSE() { return "\x7F\x2A"s; }
|
||||
std::string MQ_END() { return "\x7F\x2B"s; }
|
||||
}
|
93
soh/soh/Enhancements/randomizer/3drando/custom_messages.hpp
Normal file
93
soh/soh/Enhancements/randomizer/3drando/custom_messages.hpp
Normal file
@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "text.hpp"
|
||||
|
||||
#define QM_WHITE 0x00
|
||||
#define QM_RED 0x41
|
||||
#define QM_GREEN 0x42
|
||||
#define QM_BLUE 0x43
|
||||
#define QM_LBLUE 0x44
|
||||
#define QM_PINK 0x45
|
||||
#define QM_YELLOW 0x46
|
||||
#define QM_BLACK 0x47
|
||||
|
||||
namespace CustomMessages {
|
||||
typedef struct {
|
||||
// In the true file format, offset is the offset into the QM file.
|
||||
// In randomizer, offset will be a pointer to the text in the game's address space.
|
||||
// Since these pointers will be much larger as u32 than the original script's offsets,
|
||||
// We will be able to distinguish between original and custom text using their numerical value.
|
||||
const char* offset;
|
||||
uint32_t length;
|
||||
} MessageLanguageInfo;
|
||||
|
||||
typedef enum {
|
||||
/* 0x00 */ JAPANESE_J,
|
||||
/* 0x01 */ ENGLISH_U,
|
||||
/* 0x02 */ ENGLISH_E,
|
||||
/* 0x03 */ GERMAN_E,
|
||||
/* 0x04 */ FRENCH_E,
|
||||
/* 0x05 */ FRENCH_U,
|
||||
/* 0x06 */ SPANISH_E,
|
||||
/* 0x07 */ SPANISH_U,
|
||||
/* 0x08 */ ITALIAN_E,
|
||||
/* 0x09 */ DUTCH_E,
|
||||
} MessageLanguage;
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
uint32_t unk_04;
|
||||
uint32_t unk_08;
|
||||
uint32_t unk_0C;
|
||||
MessageLanguageInfo info[10];
|
||||
} MessageEntry; // size = 0x60
|
||||
|
||||
typedef struct {
|
||||
char magic[4]; //"QM\0\0"
|
||||
uint32_t unk_04;
|
||||
uint32_t numEntries;
|
||||
uint32_t unk_0C;
|
||||
} MessageFileHeader;
|
||||
|
||||
void CreateMessage(uint32_t textId, uint32_t unk_04, uint32_t textBoxType, uint32_t textBoxPosition,
|
||||
std::string englishText, std::string frenchText, std::string spanishText);
|
||||
void CreateMessageFromTextObject(uint32_t textId, uint32_t unk_04, uint32_t textBoxType, uint32_t textBoxPosition, const Text& text);
|
||||
|
||||
uint32_t NumMessages();
|
||||
|
||||
std::pair<const char*, uint32_t> RawMessageEntryData();
|
||||
std::pair<const char*, uint32_t> RawMessageData();
|
||||
|
||||
void CreateAlwaysIncludedMessages();
|
||||
Text AddColorsAndFormat(Text text, const std::vector<uint8_t>& colors = {});
|
||||
void ClearMessages();
|
||||
|
||||
std::string MESSAGE_END();
|
||||
std::string WAIT_FOR_INPUT();
|
||||
std::string HORIZONTAL_SPACE(uint8_t x);
|
||||
std::string GO_TO(uint16_t x);
|
||||
std::string INSTANT_TEXT_ON();
|
||||
std::string INSTANT_TEXT_OFF();
|
||||
std::string SHOP_MESSAGE_BOX();
|
||||
std::string EVENT_TRIGGER();
|
||||
std::string DELAY_FRAMES(uint8_t x);
|
||||
std::string CLOSE_AFTER(uint8_t x);
|
||||
std::string PLAYER_NAME();
|
||||
std::string PLAY_OCARINA();
|
||||
std::string ITEM_OBTAINED(uint8_t x);
|
||||
std::string SET_SPEED(uint8_t x);
|
||||
std::string SKULLTULAS_DESTROYED();
|
||||
std::string CURRENT_TIME();
|
||||
std::string UNSKIPPABLE();
|
||||
std::string TWO_WAY_CHOICE();
|
||||
std::string NEWLINE();
|
||||
std::string COLOR(uint8_t x);
|
||||
std::string CENTER_TEXT();
|
||||
std::string IF_NOT_MQ();
|
||||
std::string MQ_ELSE();
|
||||
std::string MQ_END();
|
||||
}
|
5
soh/soh/Enhancements/randomizer/3drando/debug.cpp
Normal file
5
soh/soh/Enhancements/randomizer/3drando/debug.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "debug.hpp"
|
||||
|
||||
void CitraPrint (std::string_view str) {
|
||||
|
||||
}
|
5
soh/soh/Enhancements/randomizer/3drando/debug.hpp
Normal file
5
soh/soh/Enhancements/randomizer/3drando/debug.hpp
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
void CitraPrint(std::string_view str);
|
616
soh/soh/Enhancements/randomizer/3drando/dungeon.cpp
Normal file
616
soh/soh/Enhancements/randomizer/3drando/dungeon.cpp
Normal file
@ -0,0 +1,616 @@
|
||||
#include "dungeon.hpp"
|
||||
|
||||
#include "category.hpp"
|
||||
#include "item_location.hpp"
|
||||
#include "pool_functions.hpp"
|
||||
#include "keys.hpp"
|
||||
|
||||
namespace Dungeon {
|
||||
|
||||
DungeonInfo::DungeonInfo(std::string name_, uint32_t map_, uint32_t compass_, uint32_t smallKey_, uint32_t keyRing_,
|
||||
uint32_t bossKey_, uint8_t vanillaKeyCount_, uint8_t mqKeyCount_,
|
||||
std::vector<uint32_t> vanillaLocations_,
|
||||
std::vector<uint32_t> mqLocations_,
|
||||
std::vector<uint32_t> sharedLocations_)
|
||||
: name(std::move(name_)),
|
||||
map(map_),
|
||||
compass(compass_),
|
||||
smallKey(smallKey_),
|
||||
keyRing(keyRing_),
|
||||
bossKey(bossKey_),
|
||||
vanillaKeyCount(vanillaKeyCount_),
|
||||
mqKeyCount(mqKeyCount_),
|
||||
vanillaLocations(std::move(vanillaLocations_)),
|
||||
mqLocations(std::move(mqLocations_)),
|
||||
sharedLocations(std::move(sharedLocations_)) {}
|
||||
|
||||
DungeonInfo::~DungeonInfo() = default;
|
||||
|
||||
uint32_t DungeonInfo::GetSmallKey() const {
|
||||
return smallKey;
|
||||
}
|
||||
|
||||
uint32_t DungeonInfo::GetKeyRing() const {
|
||||
return keyRing;
|
||||
}
|
||||
|
||||
uint32_t DungeonInfo::GetMap() const {
|
||||
return map;
|
||||
}
|
||||
|
||||
uint32_t DungeonInfo::GetCompass() const {
|
||||
return compass;
|
||||
}
|
||||
|
||||
uint32_t DungeonInfo::GetBossKey() const {
|
||||
return bossKey;
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaMap() {
|
||||
if (map == NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto mapLocation = FilterFromPool(dungeonLocations, [](const uint32_t loc){ return Location(loc)->IsCategory(Category::cVanillaMap); })[0];
|
||||
PlaceItemInLocation(mapLocation, map);
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaCompass() {
|
||||
if (compass == NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto compassLocation = FilterFromPool(dungeonLocations, [](const uint32_t loc){ return Location(loc)->IsCategory(Category::cVanillaCompass); })[0];
|
||||
PlaceItemInLocation(compassLocation, compass);
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaBossKey() {
|
||||
if (bossKey == NONE || bossKey == GANONS_CASTLE_BOSS_KEY) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto bossKeyLocation = FilterFromPool(dungeonLocations, [](const uint32_t loc){ return Location(loc)->IsCategory(Category::cVanillaBossKey); })[0];
|
||||
PlaceItemInLocation(bossKeyLocation, bossKey);
|
||||
}
|
||||
|
||||
void DungeonInfo::PlaceVanillaSmallKeys() {
|
||||
if (smallKey == NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dungeonLocations = GetDungeonLocations();
|
||||
auto smallKeyLocations = FilterFromPool(dungeonLocations, [](const uint32_t loc){ return Location(loc)->IsCategory(Category::cVanillaSmallKey); });
|
||||
for (auto location : smallKeyLocations) {
|
||||
PlaceItemInLocation(location, smallKey);
|
||||
}
|
||||
}
|
||||
|
||||
//Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla)
|
||||
std::vector<uint32_t> DungeonInfo::GetDungeonLocations() const {
|
||||
auto locations = masterQuest ? mqLocations : vanillaLocations;
|
||||
AddElementsToPool(locations, sharedLocations);
|
||||
return locations;
|
||||
}
|
||||
|
||||
//Gets all dungeon locations (MQ + Vanilla)
|
||||
std::vector<uint32_t> DungeonInfo::GetEveryLocation() const {
|
||||
auto locations = vanillaLocations;
|
||||
AddElementsToPool(locations, mqLocations);
|
||||
AddElementsToPool(locations, sharedLocations);
|
||||
return locations;
|
||||
}
|
||||
|
||||
DungeonInfo DekuTree = DungeonInfo("Deku Tree", DEKU_TREE_MAP, DEKU_TREE_COMPASS, NONE, NONE, NONE, 0, 0, {
|
||||
//Vanilla Locations
|
||||
DEKU_TREE_MAP_CHEST,
|
||||
DEKU_TREE_COMPASS_CHEST,
|
||||
DEKU_TREE_COMPASS_ROOM_SIDE_CHEST,
|
||||
DEKU_TREE_BASEMENT_CHEST,
|
||||
DEKU_TREE_SLINGSHOT_CHEST,
|
||||
DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST,
|
||||
DEKU_TREE_GS_BASEMENT_BACK_ROOM,
|
||||
DEKU_TREE_GS_BASEMENT_GATE,
|
||||
DEKU_TREE_GS_BASEMENT_VINES,
|
||||
DEKU_TREE_GS_COMPASS_ROOM,
|
||||
}, {
|
||||
//MQ Locations
|
||||
DEKU_TREE_MQ_MAP_CHEST,
|
||||
DEKU_TREE_MQ_COMPASS_CHEST,
|
||||
DEKU_TREE_MQ_SLINGSHOT_CHEST,
|
||||
DEKU_TREE_MQ_SLINGSHOT_ROOM_BACK_CHEST,
|
||||
DEKU_TREE_MQ_BASEMENT_CHEST,
|
||||
DEKU_TREE_MQ_BEFORE_SPINNING_LOG_CHEST,
|
||||
DEKU_TREE_MQ_AFTER_SPINNING_LOG_CHEST,
|
||||
DEKU_TREE_MQ_DEKU_SCRUB,
|
||||
DEKU_TREE_MQ_GS_LOBBY,
|
||||
DEKU_TREE_MQ_GS_COMPASS_ROOM,
|
||||
DEKU_TREE_MQ_GS_BASEMENT_GRAVES_ROOM,
|
||||
DEKU_TREE_MQ_GS_BASEMENT_BACK_ROOM,
|
||||
}, {
|
||||
//Shared Locations
|
||||
DEKU_TREE_QUEEN_GOHMA_HEART,
|
||||
QUEEN_GOHMA,
|
||||
});
|
||||
|
||||
DungeonInfo DodongosCavern = DungeonInfo("Dodongo's Cavern", DODONGOS_CAVERN_MAP, DODONGOS_CAVERN_COMPASS, NONE, NONE, NONE, 0, 0, {
|
||||
//Vanilla Locations
|
||||
DODONGOS_CAVERN_MAP_CHEST,
|
||||
DODONGOS_CAVERN_COMPASS_CHEST,
|
||||
DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST,
|
||||
DODONGOS_CAVERN_BOMB_BAG_CHEST,
|
||||
DODONGOS_CAVERN_END_OF_BRIDGE_CHEST,
|
||||
DODONGOS_CAVERN_DEKU_SCRUB_LOBBY,
|
||||
DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS,
|
||||
DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_LEFT,
|
||||
DODONGOS_CAVERN_DEKU_SCRUB_NEAR_BOMB_BAG_RIGHT,
|
||||
DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS,
|
||||
DODONGOS_CAVERN_GS_SCARECROW,
|
||||
DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS,
|
||||
DODONGOS_CAVERN_GS_BACK_ROOM,
|
||||
DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS,
|
||||
}, {
|
||||
//MQ Locations
|
||||
DODONGOS_CAVERN_MQ_MAP_CHEST,
|
||||
DODONGOS_CAVERN_MQ_BOMB_BAG_CHEST,
|
||||
DODONGOS_CAVERN_MQ_COMPASS_CHEST,
|
||||
DODONGOS_CAVERN_MQ_LARVAE_ROOM_CHEST,
|
||||
DODONGOS_CAVERN_MQ_TORCH_PUZZLE_ROOM_CHEST,
|
||||
DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST,
|
||||
DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_REAR,
|
||||
DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT,
|
||||
DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE,
|
||||
DODONGOS_CAVERN_MQ_DEKU_SCRUB_SIDE_ROOM_NEAR_LOWER_LIZALFOS,
|
||||
DODONGOS_CAVERN_MQ_GS_SCRUB_ROOM,
|
||||
DODONGOS_CAVERN_MQ_GS_SONG_OF_TIME_BLOCK_ROOM,
|
||||
DODONGOS_CAVERN_MQ_GS_LIZALFOS_ROOM,
|
||||
DODONGOS_CAVERN_MQ_GS_LARVAE_ROOM,
|
||||
DODONGOS_CAVERN_MQ_GS_BACK_AREA,
|
||||
}, {
|
||||
//Shared Locations
|
||||
DODONGOS_CAVERN_BOSS_ROOM_CHEST,
|
||||
DODONGOS_CAVERN_KING_DODONGO_HEART,
|
||||
KING_DODONGO,
|
||||
});
|
||||
|
||||
DungeonInfo JabuJabusBelly = DungeonInfo("Jabu Jabu's Belly", JABU_JABUS_BELLY_MAP, JABU_JABUS_BELLY_COMPASS, NONE, NONE, NONE, 0, 0, {
|
||||
//Vanilla Locations
|
||||
JABU_JABUS_BELLY_MAP_CHEST,
|
||||
JABU_JABUS_BELLY_COMPASS_CHEST,
|
||||
JABU_JABUS_BELLY_BOOMERANG_CHEST,
|
||||
JABU_JABUS_BELLY_DEKU_SCRUB,
|
||||
JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER,
|
||||
JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER,
|
||||
JABU_JABUS_BELLY_GS_NEAR_BOSS,
|
||||
JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM,
|
||||
}, {
|
||||
//MQ Locations
|
||||
JABU_JABUS_BELLY_MQ_FIRST_ROOM_SIDE_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_MAP_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_COMPASS_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_FALLING_LIKE_LIKE_ROOM_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST,
|
||||
JABU_JABUS_BELLY_MQ_COW,
|
||||
JABU_JABUS_BELLY_MQ_GS_TAILPASARAN_ROOM,
|
||||
JABU_JABUS_BELLY_MQ_GS_INVISIBLE_ENEMIES_ROOM,
|
||||
JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM,
|
||||
JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS,
|
||||
}, {
|
||||
//Shared Locations
|
||||
JABU_JABUS_BELLY_BARINADE_HEART,
|
||||
BARINADE,
|
||||
});
|
||||
|
||||
DungeonInfo ForestTemple = DungeonInfo("Forest Temple", FOREST_TEMPLE_MAP, FOREST_TEMPLE_COMPASS, FOREST_TEMPLE_SMALL_KEY, FOREST_TEMPLE_KEY_RING, FOREST_TEMPLE_BOSS_KEY, 5, 6, {
|
||||
//Vanilla Locations
|
||||
FOREST_TEMPLE_FIRST_ROOM_CHEST,
|
||||
FOREST_TEMPLE_FIRST_STALFOS_CHEST,
|
||||
FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST,
|
||||
FOREST_TEMPLE_MAP_CHEST,
|
||||
FOREST_TEMPLE_WELL_CHEST,
|
||||
FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST,
|
||||
FOREST_TEMPLE_EYE_SWITCH_CHEST,
|
||||
FOREST_TEMPLE_BOSS_KEY_CHEST,
|
||||
FOREST_TEMPLE_FLOORMASTER_CHEST,
|
||||
FOREST_TEMPLE_BOW_CHEST,
|
||||
FOREST_TEMPLE_RED_POE_CHEST,
|
||||
FOREST_TEMPLE_BLUE_POE_CHEST,
|
||||
FOREST_TEMPLE_BASEMENT_CHEST,
|
||||
FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD,
|
||||
FOREST_TEMPLE_GS_FIRST_ROOM,
|
||||
FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD,
|
||||
FOREST_TEMPLE_GS_LOBBY,
|
||||
FOREST_TEMPLE_GS_BASEMENT,
|
||||
}, {
|
||||
//MQ Locations
|
||||
FOREST_TEMPLE_MQ_FIRST_ROOM_CHEST,
|
||||
FOREST_TEMPLE_MQ_WOLFOS_CHEST,
|
||||
FOREST_TEMPLE_MQ_BOW_CHEST,
|
||||
FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_LOWER_CHEST,
|
||||
FOREST_TEMPLE_MQ_RAISED_ISLAND_COURTYARD_UPPER_CHEST,
|
||||
FOREST_TEMPLE_MQ_WELL_CHEST,
|
||||
FOREST_TEMPLE_MQ_MAP_CHEST,
|
||||
FOREST_TEMPLE_MQ_COMPASS_CHEST,
|
||||
FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST,
|
||||
FOREST_TEMPLE_MQ_BASEMENT_CHEST,
|
||||
FOREST_TEMPLE_MQ_REDEAD_CHEST,
|
||||
FOREST_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
FOREST_TEMPLE_MQ_GS_FIRST_HALLWAY,
|
||||
FOREST_TEMPLE_MQ_GS_BLOCK_PUSH_ROOM,
|
||||
FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD,
|
||||
FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD,
|
||||
FOREST_TEMPLE_MQ_GS_WELL,
|
||||
}, {
|
||||
//Shared Locations
|
||||
FOREST_TEMPLE_PHANTOM_GANON_HEART,
|
||||
PHANTOM_GANON,
|
||||
});
|
||||
|
||||
DungeonInfo FireTemple = DungeonInfo("Fire Temple", FIRE_TEMPLE_MAP, FIRE_TEMPLE_COMPASS, FIRE_TEMPLE_SMALL_KEY, FIRE_TEMPLE_KEY_RING, FIRE_TEMPLE_BOSS_KEY, 8, 5, {
|
||||
//Vanilla Locations
|
||||
FIRE_TEMPLE_NEAR_BOSS_CHEST,
|
||||
FIRE_TEMPLE_FLARE_DANCER_CHEST,
|
||||
FIRE_TEMPLE_BOSS_KEY_CHEST,
|
||||
FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST,
|
||||
FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST,
|
||||
FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST,
|
||||
FIRE_TEMPLE_BOULDER_MAZE_UPPER_CHEST,
|
||||
FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST,
|
||||
FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST,
|
||||
FIRE_TEMPLE_SCARECROW_CHEST,
|
||||
FIRE_TEMPLE_MAP_CHEST,
|
||||
FIRE_TEMPLE_COMPASS_CHEST,
|
||||
FIRE_TEMPLE_HIGHEST_GORON_CHEST,
|
||||
FIRE_TEMPLE_MEGATON_HAMMER_CHEST,
|
||||
FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM,
|
||||
FIRE_TEMPLE_GS_BOSS_KEY_LOOP,
|
||||
FIRE_TEMPLE_GS_BOULDER_MAZE,
|
||||
FIRE_TEMPLE_GS_SCARECROW_TOP,
|
||||
FIRE_TEMPLE_GS_SCARECROW_CLIMB,
|
||||
}, {
|
||||
//MQ Locations
|
||||
FIRE_TEMPLE_MQ_NEAR_BOSS_CHEST,
|
||||
FIRE_TEMPLE_MQ_MEGATON_HAMMER_CHEST,
|
||||
FIRE_TEMPLE_MQ_COMPASS_CHEST,
|
||||
FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST,
|
||||
FIRE_TEMPLE_MQ_LIZALFOS_MAZE_UPPER_CHEST,
|
||||
FIRE_TEMPLE_MQ_CHEST_ON_FIRE,
|
||||
FIRE_TEMPLE_MQ_MAP_ROOM_SIDE_CHEST,
|
||||
FIRE_TEMPLE_MQ_MAP_CHEST,
|
||||
FIRE_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
FIRE_TEMPLE_MQ_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST,
|
||||
FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST,
|
||||
FIRE_TEMPLE_MQ_FREESTANDING_KEY,
|
||||
FIRE_TEMPLE_MQ_GS_ABOVE_FIRE_WALL_MAZE,
|
||||
FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_CENTER,
|
||||
FIRE_TEMPLE_MQ_GS_BIG_LAVA_ROOM_OPEN_DOOR,
|
||||
FIRE_TEMPLE_MQ_GS_FIRE_WALL_MAZE_SIDE_ROOM,
|
||||
FIRE_TEMPLE_MQ_GS_SKULL_ON_FIRE,
|
||||
}, {
|
||||
//Shared Locations
|
||||
FIRE_TEMPLE_VOLVAGIA_HEART,
|
||||
VOLVAGIA,
|
||||
});
|
||||
|
||||
DungeonInfo WaterTemple = DungeonInfo("Water Temple", WATER_TEMPLE_MAP, WATER_TEMPLE_COMPASS, WATER_TEMPLE_SMALL_KEY, WATER_TEMPLE_KEY_RING, WATER_TEMPLE_BOSS_KEY, 6, 2, {
|
||||
//Vanilla Locations
|
||||
WATER_TEMPLE_MAP_CHEST,
|
||||
WATER_TEMPLE_COMPASS_CHEST,
|
||||
WATER_TEMPLE_TORCHES_CHEST,
|
||||
WATER_TEMPLE_DRAGON_CHEST,
|
||||
WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST,
|
||||
WATER_TEMPLE_CENTRAL_PILLAR_CHEST,
|
||||
WATER_TEMPLE_CRACKED_WALL_CHEST,
|
||||
WATER_TEMPLE_BOSS_KEY_CHEST,
|
||||
WATER_TEMPLE_LONGSHOT_CHEST,
|
||||
WATER_TEMPLE_RIVER_CHEST,
|
||||
WATER_TEMPLE_GS_BEHIND_GATE,
|
||||
WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM,
|
||||
WATER_TEMPLE_GS_CENTRAL_PILLAR,
|
||||
WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST,
|
||||
WATER_TEMPLE_GS_RIVER,
|
||||
}, {
|
||||
//MQ Locations
|
||||
WATER_TEMPLE_MQ_CENTRAL_PILLAR_CHEST,
|
||||
WATER_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
WATER_TEMPLE_MQ_LONGSHOT_CHEST,
|
||||
WATER_TEMPLE_MQ_COMPASS_CHEST,
|
||||
WATER_TEMPLE_MQ_MAP_CHEST,
|
||||
WATER_TEMPLE_MQ_FREESTANDING_KEY,
|
||||
WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH,
|
||||
WATER_TEMPLE_MQ_GS_FREESTANDING_KEY_AREA,
|
||||
WATER_TEMPLE_MQ_GS_LIZALFOS_HALLWAY,
|
||||
WATER_TEMPLE_MQ_GS_RIVER,
|
||||
WATER_TEMPLE_MQ_GS_TRIPLE_WALL_TORCH,
|
||||
}, {
|
||||
//Shared Locations
|
||||
WATER_TEMPLE_MORPHA_HEART,
|
||||
MORPHA,
|
||||
});
|
||||
|
||||
DungeonInfo SpiritTemple = DungeonInfo("Spirit Temple", SPIRIT_TEMPLE_MAP, SPIRIT_TEMPLE_COMPASS, SPIRIT_TEMPLE_SMALL_KEY, SPIRIT_TEMPLE_KEY_RING, SPIRIT_TEMPLE_BOSS_KEY, 5, 7, {
|
||||
//Vanilla Locations
|
||||
SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST,
|
||||
SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST,
|
||||
SPIRIT_TEMPLE_COMPASS_CHEST,
|
||||
SPIRIT_TEMPLE_EARLY_ADULT_RIGHT_CHEST,
|
||||
SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST,
|
||||
SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST,
|
||||
SPIRIT_TEMPLE_MAP_CHEST,
|
||||
SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST,
|
||||
SPIRIT_TEMPLE_CHILD_CLIMB_EAST_CHEST,
|
||||
SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST,
|
||||
SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST,
|
||||
SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST,
|
||||
SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST,
|
||||
SPIRIT_TEMPLE_HALLWAY_LEFT_INVISIBLE_CHEST,
|
||||
SPIRIT_TEMPLE_HALLWAY_RIGHT_INVISIBLE_CHEST,
|
||||
SPIRIT_TEMPLE_BOSS_KEY_CHEST,
|
||||
SPIRIT_TEMPLE_TOPMOST_CHEST,
|
||||
SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM,
|
||||
SPIRIT_TEMPLE_GS_BOULDER_ROOM,
|
||||
SPIRIT_TEMPLE_GS_LOBBY,
|
||||
SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM,
|
||||
SPIRIT_TEMPLE_GS_METAL_FENCE,
|
||||
}, {
|
||||
//MQ Locations
|
||||
SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_LEFT_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_CHILD_HAMMER_SWITCH_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_MAP_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_COMPASS_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_LEEVER_ROOM_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_CHEST_SWITCH_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST,
|
||||
SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM,
|
||||
SPIRIT_TEMPLE_MQ_GS_LEEVER_ROOM,
|
||||
SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST,
|
||||
SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_NORTH,
|
||||
SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM,
|
||||
}, {
|
||||
//Shared Locations
|
||||
SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST,
|
||||
SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST,
|
||||
SPIRIT_TEMPLE_TWINROVA_HEART,
|
||||
TWINROVA,
|
||||
});
|
||||
|
||||
DungeonInfo ShadowTemple = DungeonInfo("Shadow Temple", SHADOW_TEMPLE_MAP, SHADOW_TEMPLE_COMPASS, SHADOW_TEMPLE_SMALL_KEY, SHADOW_TEMPLE_KEY_RING, SHADOW_TEMPLE_BOSS_KEY, 5, 6, {
|
||||
//Vanilla Locations
|
||||
SHADOW_TEMPLE_MAP_CHEST,
|
||||
SHADOW_TEMPLE_HOVER_BOOTS_CHEST,
|
||||
SHADOW_TEMPLE_COMPASS_CHEST,
|
||||
SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST,
|
||||
SHADOW_TEMPLE_INVISIBLE_BLADES_VISIBLE_CHEST,
|
||||
SHADOW_TEMPLE_INVISIBLE_BLADES_INVISIBLE_CHEST,
|
||||
SHADOW_TEMPLE_FALLING_SPIKES_LOWER_CHEST,
|
||||
SHADOW_TEMPLE_FALLING_SPIKES_UPPER_CHEST,
|
||||
SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST,
|
||||
SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST,
|
||||
SHADOW_TEMPLE_WIND_HINT_CHEST,
|
||||
SHADOW_TEMPLE_AFTER_WIND_ENEMY_CHEST,
|
||||
SHADOW_TEMPLE_AFTER_WIND_HIDDEN_CHEST,
|
||||
SHADOW_TEMPLE_SPIKE_WALLS_LEFT_CHEST,
|
||||
SHADOW_TEMPLE_BOSS_KEY_CHEST,
|
||||
SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST,
|
||||
SHADOW_TEMPLE_FREESTANDING_KEY,
|
||||
SHADOW_TEMPLE_GS_SINGLE_GIANT_POT,
|
||||
SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM,
|
||||
SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT,
|
||||
SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM,
|
||||
SHADOW_TEMPLE_GS_NEAR_SHIP,
|
||||
}, {
|
||||
//MQ Locations
|
||||
SHADOW_TEMPLE_MQ_COMPASS_CHEST,
|
||||
SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST,
|
||||
SHADOW_TEMPLE_MQ_EARLY_GIBDOS_CHEST,
|
||||
SHADOW_TEMPLE_MQ_MAP_CHEST,
|
||||
SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST,
|
||||
SHADOW_TEMPLE_MQ_FALLING_SPIKES_SWITCH_CHEST,
|
||||
SHADOW_TEMPLE_MQ_FALLING_SPIKES_LOWER_CHEST,
|
||||
SHADOW_TEMPLE_MQ_FALLING_SPIKES_UPPER_CHEST,
|
||||
SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST,
|
||||
SHADOW_TEMPLE_MQ_BOSS_KEY_CHEST,
|
||||
SHADOW_TEMPLE_MQ_SPIKE_WALLS_LEFT_CHEST,
|
||||
SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST,
|
||||
SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST,
|
||||
SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST,
|
||||
SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST,
|
||||
SHADOW_TEMPLE_MQ_WIND_HINT_CHEST,
|
||||
SHADOW_TEMPLE_MQ_AFTER_WIND_HIDDEN_CHEST,
|
||||
SHADOW_TEMPLE_MQ_AFTER_WIND_ENEMY_CHEST,
|
||||
SHADOW_TEMPLE_MQ_NEAR_SHIP_INVISIBLE_CHEST,
|
||||
SHADOW_TEMPLE_MQ_FREESTANDING_KEY,
|
||||
SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM,
|
||||
SHADOW_TEMPLE_MQ_GS_WIND_HINT_ROOM,
|
||||
SHADOW_TEMPLE_MQ_GS_AFTER_WIND,
|
||||
SHADOW_TEMPLE_MQ_GS_AFTER_SHIP,
|
||||
SHADOW_TEMPLE_MQ_GS_NEAR_BOSS,
|
||||
}, {
|
||||
//Shared Locations
|
||||
SHADOW_TEMPLE_BONGO_BONGO_HEART,
|
||||
BONGO_BONGO,
|
||||
});
|
||||
|
||||
DungeonInfo BottomOfTheWell = DungeonInfo("Bottom of the Well", BOTTOM_OF_THE_WELL_MAP, BOTTOM_OF_THE_WELL_COMPASS, BOTTOM_OF_THE_WELL_SMALL_KEY, BOTTOM_OF_THE_WELL_KEY_RING, NONE, 3, 2, {
|
||||
//Vanilla Locations
|
||||
BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST,
|
||||
BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST,
|
||||
BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST,
|
||||
BOTTOM_OF_THE_WELL_COMPASS_CHEST,
|
||||
BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST,
|
||||
BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST,
|
||||
BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST,
|
||||
BOTTOM_OF_THE_WELL_INVISIBLE_CHEST,
|
||||
BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST,
|
||||
BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST,
|
||||
BOTTOM_OF_THE_WELL_MAP_CHEST,
|
||||
BOTTOM_OF_THE_WELL_FIRE_KEESE_CHEST,
|
||||
BOTTOM_OF_THE_WELL_LIKE_LIKE_CHEST,
|
||||
BOTTOM_OF_THE_WELL_FREESTANDING_KEY,
|
||||
BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE,
|
||||
BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM,
|
||||
BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM,
|
||||
}, {
|
||||
//MQ Locations
|
||||
BOTTOM_OF_THE_WELL_MQ_MAP_CHEST,
|
||||
BOTTOM_OF_THE_WELL_MQ_LENS_OF_TRUTH_CHEST,
|
||||
BOTTOM_OF_THE_WELL_MQ_COMPASS_CHEST,
|
||||
BOTTOM_OF_THE_WELL_MQ_DEAD_HAND_FREESTANDING_KEY,
|
||||
BOTTOM_OF_THE_WELL_MQ_EAST_INNER_ROOM_FREESTANDING_KEY,
|
||||
BOTTOM_OF_THE_WELL_MQ_GS_BASEMENT,
|
||||
BOTTOM_OF_THE_WELL_MQ_GS_COFFIN_ROOM,
|
||||
BOTTOM_OF_THE_WELL_MQ_GS_WEST_INNER_ROOM,
|
||||
}, {});
|
||||
|
||||
DungeonInfo IceCavern = DungeonInfo("Ice Cavern", ICE_CAVERN_MAP, ICE_CAVERN_COMPASS, NONE, NONE, NONE, 0, 0, {
|
||||
//Vanilla Locations
|
||||
ICE_CAVERN_MAP_CHEST,
|
||||
ICE_CAVERN_COMPASS_CHEST,
|
||||
ICE_CAVERN_IRON_BOOTS_CHEST,
|
||||
ICE_CAVERN_FREESTANDING_POH,
|
||||
ICE_CAVERN_GS_PUSH_BLOCK_ROOM,
|
||||
ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM,
|
||||
ICE_CAVERN_GS_HEART_PIECE_ROOM,
|
||||
}, {
|
||||
//MQ Locations
|
||||
ICE_CAVERN_MQ_IRON_BOOTS_CHEST,
|
||||
ICE_CAVERN_MQ_COMPASS_CHEST,
|
||||
ICE_CAVERN_MQ_MAP_CHEST,
|
||||
ICE_CAVERN_MQ_FREESTANDING_POH,
|
||||
ICE_CAVERN_MQ_GS_SCARECROW,
|
||||
ICE_CAVERN_MQ_GS_ICE_BLOCK,
|
||||
ICE_CAVERN_MQ_GS_RED_ICE,
|
||||
}, {
|
||||
//Shared Locations
|
||||
SHEIK_IN_ICE_CAVERN,
|
||||
});
|
||||
|
||||
DungeonInfo GerudoTrainingGrounds = DungeonInfo("Gerudo Training Grounds", NONE, NONE, GERUDO_TRAINING_GROUNDS_SMALL_KEY, GERUDO_TRAINING_GROUNDS_KEY_RING, NONE, 9, 3, {
|
||||
//Vanilla Locations
|
||||
GERUDO_TRAINING_GROUNDS_LOBBY_LEFT_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_LOBBY_RIGHT_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_STALFOS_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_BEAMOS_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_HIDDEN_CEILING_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MAZE_PATH_FIRST_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MAZE_PATH_SECOND_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MAZE_PATH_THIRD_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MAZE_PATH_FINAL_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MAZE_RIGHT_CENTRAL_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MAZE_RIGHT_SIDE_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_UNDERWATER_SILVER_RUPEE_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_HAMMER_ROOM_CLEAR_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_HAMMER_ROOM_SWITCH_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_EYE_STATUE_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_NEAR_SCARECROW_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_BEFORE_HEAVY_BLOCK_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_FIRST_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_SECOND_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_THIRD_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_FOURTH_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_FREESTANDING_KEY,
|
||||
}, {
|
||||
//MQ Locations
|
||||
GERUDO_TRAINING_GROUNDS_MQ_LOBBY_RIGHT_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_LOBBY_LEFT_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_FIRST_IRON_KNUCKLE_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_BEFORE_HEAVY_BLOCK_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_EYE_STATUE_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_FLAME_CIRCLE_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_SECOND_IRON_KNUCKLE_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_DINOLFOS_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_ICE_ARROWS_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_MAZE_RIGHT_CENTRAL_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_MAZE_PATH_FIRST_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_MAZE_RIGHT_SIDE_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_MAZE_PATH_THIRD_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_MAZE_PATH_SECOND_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_HIDDEN_CEILING_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER_SILVER_RUPEE_CHEST,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_HEAVY_BLOCK_CHEST,
|
||||
}, {});
|
||||
|
||||
DungeonInfo GanonsCastle = DungeonInfo("Ganon's Castle", NONE, NONE, GANONS_CASTLE_SMALL_KEY, GANONS_CASTLE_KEY_RING, GANONS_CASTLE_BOSS_KEY, 2, 3, {
|
||||
//Vanilla Locations
|
||||
GANONS_CASTLE_FOREST_TRIAL_CHEST,
|
||||
GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST,
|
||||
GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST,
|
||||
GANONS_CASTLE_SHADOW_TRIAL_FRONT_CHEST,
|
||||
GANONS_CASTLE_SHADOW_TRIAL_GOLDEN_GAUNTLETS_CHEST,
|
||||
GANONS_CASTLE_SPIRIT_TRIAL_CRYSTAL_SWITCH_CHEST,
|
||||
GANONS_CASTLE_SPIRIT_TRIAL_INVISIBLE_CHEST,
|
||||
GANONS_CASTLE_LIGHT_TRIAL_FIRST_LEFT_CHEST,
|
||||
GANONS_CASTLE_LIGHT_TRIAL_SECOND_LEFT_CHEST,
|
||||
GANONS_CASTLE_LIGHT_TRIAL_THIRD_LEFT_CHEST,
|
||||
GANONS_CASTLE_LIGHT_TRIAL_FIRST_RIGHT_CHEST,
|
||||
GANONS_CASTLE_LIGHT_TRIAL_SECOND_RIGHT_CHEST,
|
||||
GANONS_CASTLE_LIGHT_TRIAL_THIRD_RIGHT_CHEST,
|
||||
GANONS_CASTLE_LIGHT_TRIAL_INVISIBLE_ENEMIES_CHEST,
|
||||
GANONS_CASTLE_LIGHT_TRIAL_LULLABY_CHEST,
|
||||
GANONS_CASTLE_DEKU_SCRUB_LEFT,
|
||||
GANONS_CASTLE_DEKU_SCRUB_CENTER_LEFT,
|
||||
GANONS_CASTLE_DEKU_SCRUB_CENTER_RIGHT,
|
||||
GANONS_CASTLE_DEKU_SCRUB_RIGHT,
|
||||
}, {
|
||||
//MQ Locations
|
||||
GANONS_CASTLE_MQ_WATER_TRIAL_CHEST,
|
||||
GANONS_CASTLE_MQ_FOREST_TRIAL_EYE_SWITCH_CHEST,
|
||||
GANONS_CASTLE_MQ_FOREST_TRIAL_FROZEN_EYE_SWITCH_CHEST,
|
||||
GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST,
|
||||
GANONS_CASTLE_MQ_SHADOW_TRIAL_BOMB_FLOWER_CHEST,
|
||||
GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST,
|
||||
GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST,
|
||||
GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST,
|
||||
GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST,
|
||||
GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_FRONT_LEFT_CHEST,
|
||||
GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST,
|
||||
GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST,
|
||||
GANONS_CASTLE_MQ_FOREST_TRIAL_FREESTANDING_KEY,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUB_RIGHT,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_LEFT,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUB_CENTER_RIGHT,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUB_LEFT,
|
||||
}, {
|
||||
//Shared Locations
|
||||
GANONS_TOWER_BOSS_KEY_CHEST,
|
||||
GANON,
|
||||
});
|
||||
|
||||
const DungeonArray dungeonList = {
|
||||
&DekuTree,
|
||||
&DodongosCavern,
|
||||
&JabuJabusBelly,
|
||||
&ForestTemple,
|
||||
&FireTemple,
|
||||
&WaterTemple,
|
||||
&SpiritTemple,
|
||||
&ShadowTemple,
|
||||
&BottomOfTheWell,
|
||||
&IceCavern,
|
||||
&GerudoTrainingGrounds,
|
||||
&GanonsCastle,
|
||||
};
|
||||
|
||||
} //namespace Dungeon
|
104
soh/soh/Enhancements/randomizer/3drando/dungeon.hpp
Normal file
104
soh/soh/Enhancements/randomizer/3drando/dungeon.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "keys.hpp"
|
||||
|
||||
namespace Dungeon {
|
||||
class DungeonInfo {
|
||||
public:
|
||||
DungeonInfo(std::string name_, uint32_t map_, uint32_t compass_, uint32_t smallKey_, uint32_t keyRing_, uint32_t bossKey_,
|
||||
uint8_t vanillaKeyCount_, uint8_t mqKeyCount_,
|
||||
std::vector<uint32_t> vanillaLocations_,
|
||||
std::vector<uint32_t> mqLocations_,
|
||||
std::vector<uint32_t> sharedLocations_);
|
||||
~DungeonInfo();
|
||||
|
||||
const std::string& GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
void SetMQ() {
|
||||
masterQuest = true;
|
||||
}
|
||||
|
||||
void ClearMQ() {
|
||||
masterQuest = false;
|
||||
}
|
||||
|
||||
bool IsMQ() const {
|
||||
return masterQuest;
|
||||
}
|
||||
|
||||
void SetKeyRing() {
|
||||
hasKeyRing = true;
|
||||
}
|
||||
|
||||
void ClearKeyRing() {
|
||||
hasKeyRing = false;
|
||||
}
|
||||
|
||||
bool HasKeyRing() const {
|
||||
return hasKeyRing;
|
||||
}
|
||||
|
||||
bool IsVanilla() const {
|
||||
return !masterQuest;
|
||||
}
|
||||
|
||||
uint8_t GetSmallKeyCount() const {
|
||||
return (masterQuest) ? mqKeyCount : vanillaKeyCount;
|
||||
}
|
||||
|
||||
uint32_t GetSmallKey() const;
|
||||
uint32_t GetKeyRing() const;
|
||||
uint32_t GetMap() const;
|
||||
uint32_t GetCompass() const;
|
||||
uint32_t GetBossKey() const;
|
||||
|
||||
void PlaceVanillaMap();
|
||||
void PlaceVanillaCompass();
|
||||
void PlaceVanillaBossKey();
|
||||
void PlaceVanillaSmallKeys();
|
||||
|
||||
// Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla)
|
||||
std::vector<uint32_t> GetDungeonLocations() const;
|
||||
|
||||
// Gets all dungeon locations (MQ + Vanilla)
|
||||
std::vector<uint32_t> GetEveryLocation() const;
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
uint32_t map;
|
||||
uint32_t compass;
|
||||
uint32_t smallKey;
|
||||
uint32_t keyRing;
|
||||
uint32_t 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;
|
||||
};
|
||||
|
||||
extern DungeonInfo DekuTree;
|
||||
extern DungeonInfo DodongosCavern;
|
||||
extern DungeonInfo JabuJabusBelly;
|
||||
extern DungeonInfo ForestTemple;
|
||||
extern DungeonInfo FireTemple;
|
||||
extern DungeonInfo WaterTemple;
|
||||
extern DungeonInfo SpiritTemple;
|
||||
extern DungeonInfo ShadowTemple;
|
||||
extern DungeonInfo BottomOfTheWell;
|
||||
extern DungeonInfo IceCavern;
|
||||
extern DungeonInfo GerudoTrainingGrounds;
|
||||
extern DungeonInfo GanonsCastle;
|
||||
|
||||
using DungeonArray = std::array<DungeonInfo*, 12>;
|
||||
|
||||
extern const DungeonArray dungeonList;
|
||||
} // namespace Dungeon
|
877
soh/soh/Enhancements/randomizer/3drando/entrance.cpp
Normal file
877
soh/soh/Enhancements/randomizer/3drando/entrance.cpp
Normal file
@ -0,0 +1,877 @@
|
||||
#include "entrance.hpp"
|
||||
|
||||
#include "fill.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "item_list.hpp"
|
||||
#include "item_pool.hpp"
|
||||
#include "item_location.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "hints.hpp"
|
||||
#include "location_access.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <Lib/spdlog/include/spdlog/spdlog.h>
|
||||
|
||||
std::list<EntranceOverride> entranceOverrides = {};
|
||||
bool noRandomEntrances = false;
|
||||
static bool entranceShuffleFailure = false;
|
||||
static int totalRandomizableEntrances = 0;
|
||||
static int curNumRandomizedEntrances = 0;
|
||||
|
||||
typedef struct {
|
||||
EntranceType type;
|
||||
uint32_t parentRegion;
|
||||
uint32_t connectedRegion;
|
||||
int16_t index;
|
||||
int16_t blueWarp;
|
||||
} EntranceLinkInfo;
|
||||
//primary, secondary
|
||||
using EntranceInfoPair = std::pair<EntranceLinkInfo, EntranceLinkInfo>;
|
||||
using EntrancePair = std::pair<Entrance*, Entrance*>;
|
||||
|
||||
//The entrance randomization algorithm used here is a direct copy of
|
||||
//the algorithm used in the original N64 randomizer (except now in C++ instead
|
||||
//of python). It may be easier to understand the algorithm by looking at the
|
||||
//base randomizer's code instead:
|
||||
// https://github.com/TestRunnerSRL/OoT-Randomizer/blob/Dev/EntranceShuffle.py
|
||||
|
||||
// Updates the user on how many entrances are currently shuffled
|
||||
static void DisplayEntranceProgress() {
|
||||
std::string dots = ".";
|
||||
float progress = (float)curNumRandomizedEntrances / (float)totalRandomizableEntrances;
|
||||
if (progress > 0.33) {
|
||||
dots += ".";
|
||||
} else {
|
||||
dots += " ";
|
||||
}
|
||||
if (progress > 0.66) {
|
||||
dots += ".";
|
||||
} else {
|
||||
dots += " ";
|
||||
}
|
||||
printf("\x1b[7;29H%s", dots.c_str());
|
||||
#ifdef ENABLE_DEBUG
|
||||
if (curNumRandomizedEntrances == totalRandomizableEntrances) {
|
||||
Areas::DumpWorldGraph("Finish Validation");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
|
||||
for (auto& entrancePair: entranceShuffleTable) {
|
||||
|
||||
auto& forwardEntry = entrancePair.first;
|
||||
auto& returnEntry = entrancePair.second;
|
||||
|
||||
//set data
|
||||
Entrance* forwardEntrance = AreaTable(forwardEntry.parentRegion)->GetExit(forwardEntry.connectedRegion);
|
||||
forwardEntrance->SetIndex(forwardEntry.index);
|
||||
forwardEntrance->SetBlueWarp(forwardEntry.blueWarp);
|
||||
forwardEntrance->SetType(forwardEntry.type);
|
||||
forwardEntrance->SetAsPrimary();
|
||||
// if type == 'Grotto':
|
||||
// forward_entrance.data['index'] = 0x0700 + forward_entrance.data['grotto_id']
|
||||
if (returnEntry.parentRegion != NONE) {
|
||||
Entrance* returnEntrance = AreaTable(returnEntry.parentRegion)->GetExit(returnEntry.connectedRegion);
|
||||
returnEntrance->SetIndex(returnEntry.index);
|
||||
returnEntrance->SetBlueWarp(returnEntry.blueWarp);
|
||||
returnEntrance->SetType(returnEntry.type);
|
||||
forwardEntrance->BindTwoWay(returnEntrance);
|
||||
// if type == 'Grotto':
|
||||
// return_entrance.data['index'] = 0x0800 + return_entrance.data['grotto_id']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<Entrance*> AssumeEntrancePool(std::vector<Entrance*>& entrancePool) {
|
||||
std::vector<Entrance*> assumedPool = {};
|
||||
for (Entrance* entrance : entrancePool) {
|
||||
Entrance* assumedForward = entrance->AssumeReachable();
|
||||
if (entrance->GetReverse() != nullptr /*&& entrances are not decoupled*/) {
|
||||
Entrance* assumedReturn = entrance->GetReverse()->AssumeReachable();
|
||||
//mixed pool assumption stuff
|
||||
assumedForward->BindTwoWay(assumedReturn);
|
||||
}
|
||||
assumedPool.push_back(assumedForward);
|
||||
}
|
||||
return assumedPool;
|
||||
}
|
||||
|
||||
//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*, uint32_t> originalConnectedRegions = {};
|
||||
std::set<Entrance*> entrancesToDisconnect = {};
|
||||
for (Entrance* entrance : assumedEntrances) {
|
||||
entrancesToDisconnect.insert(entrance);
|
||||
if (entrance->GetReverse() != nullptr) {
|
||||
entrancesToDisconnect.insert(entrance->GetReverse());
|
||||
}
|
||||
}
|
||||
|
||||
//disconnect each entrance temporarily to find restrictive vs soft entrances
|
||||
//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) {
|
||||
originalConnectedRegions[entrance] = entrance->Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Entrance*> restrictiveEntrances = {};
|
||||
std::vector<Entrance*> softEntrances = {};
|
||||
|
||||
Logic::LogicReset();
|
||||
// //Apply the effects of all advancement items to search for entrance accessibility
|
||||
std::vector<uint32_t> items = FilterFromPool(ItemPool, [](const auto i){ return ItemTable(i).IsAdvancement();});
|
||||
for (uint32_t unplacedItem : items) {
|
||||
ItemTable(unplacedItem).ApplyEffect();
|
||||
}
|
||||
// run a search to see what's accessible
|
||||
GetAccessibleLocations({});
|
||||
|
||||
for (Entrance* entrance : entrancesToSplit) {
|
||||
// if an entrance is accessible at all times of day by both ages, it's a soft entrance with no restrictions
|
||||
if (entrance->ConditionsMet(true)) {
|
||||
softEntrances.push_back(entrance);
|
||||
} else {
|
||||
restrictiveEntrances.push_back(entrance);
|
||||
}
|
||||
}
|
||||
|
||||
//Reconnect all disconnected entrances
|
||||
for (Entrance* entrance : entrancesToDisconnect) {
|
||||
entrance->Connect(originalConnectedRegions[entrance]);
|
||||
}
|
||||
|
||||
return {restrictiveEntrances, softEntrances};
|
||||
}
|
||||
|
||||
static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::vector<EntrancePair>& rollbacks) {
|
||||
|
||||
//Entrances shouldn't connect to their own scene, fail in this situation
|
||||
if (entrance->GetParentRegion()->scene != "" && entrance->GetParentRegion()->scene == target->GetConnectedRegion()->scene) {
|
||||
auto message = "Entrance " + entrance->GetName() + " attempted to connect with own scene target " + target->to_string() + ". Connection failed.\n";
|
||||
SPDLOG_INFO(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
//one-way entrance stuff
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Change connections between an entrance and a target assumed entrance, in order to test the connections afterwards if necessary
|
||||
static void ChangeConnections(Entrance* entrance, Entrance* targetEntrance) {
|
||||
auto message = "Attempting to connect " + entrance->GetName() + " to " + targetEntrance->to_string() + "\n";
|
||||
SPDLOG_INFO(message);
|
||||
entrance->Connect(targetEntrance->Disconnect());
|
||||
entrance->SetReplacement(targetEntrance->GetReplacement());
|
||||
if (entrance->GetReverse() != nullptr /*&& entrances aren't decoupled*/) {
|
||||
targetEntrance->GetReplacement()->GetReverse()->Connect(entrance->GetReverse()->GetAssumed()->Disconnect());
|
||||
targetEntrance->GetReplacement()->GetReverse()->SetReplacement(entrance->GetReverse());
|
||||
}
|
||||
}
|
||||
|
||||
static void RestoreConnections(Entrance* entrance, Entrance* targetEntrance) {
|
||||
targetEntrance->Connect(entrance->Disconnect());
|
||||
entrance->SetReplacement(nullptr);
|
||||
if (entrance->GetReverse() != nullptr /*&& entrances are not decoupled*/) {
|
||||
entrance->GetReverse()->GetAssumed()->Connect(targetEntrance->GetReplacement()->GetReverse()->Disconnect());
|
||||
targetEntrance->GetReplacement()->GetReverse()->SetReplacement(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void DeleteTargetEntrance(Entrance* targetEntrance) {
|
||||
if (targetEntrance->GetConnectedRegionKey() != NONE) {
|
||||
targetEntrance->Disconnect();
|
||||
}
|
||||
if (targetEntrance->GetParentRegionKey() != NONE) {
|
||||
targetEntrance->GetParentRegion()->RemoveExit(targetEntrance);
|
||||
targetEntrance->SetParentRegion(NONE);
|
||||
}
|
||||
}
|
||||
|
||||
static void ConfirmReplacement(Entrance* entrance, Entrance* targetEntrance) {
|
||||
DeleteTargetEntrance(targetEntrance);
|
||||
if (entrance->GetReverse() != nullptr /*&& entrances are not decoupled*/) {
|
||||
auto replacedReverse = targetEntrance->GetReplacement()->GetReverse();
|
||||
DeleteTargetEntrance(replacedReverse->GetReverse()->GetAssumed());
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether or not we can affirm the entrance can never be accessed as the given age
|
||||
static bool EntranceUnreachableAs(Entrance* entrance, uint8_t age, std::vector<Entrance*>& alreadyChecked) {
|
||||
|
||||
if (entrance == nullptr) {
|
||||
SPDLOG_INFO("Entrance is nullptr in EntranceUnreachableAs()");
|
||||
return true;
|
||||
}
|
||||
|
||||
alreadyChecked.push_back(entrance);
|
||||
auto type = entrance->GetType();
|
||||
|
||||
// The following cases determine when we say an entrance is not safe to affirm unreachable as the given age
|
||||
if (type == EntranceType::WarpSong || type == EntranceType::Overworld) {
|
||||
// Note that we consider all overworld entrances as potentially accessible as both ages, to be completely safe
|
||||
return false;
|
||||
} else if (type == EntranceType::OwlDrop) {
|
||||
return age == AGE_ADULT;
|
||||
} else if (type == EntranceType::Spawn && entrance->GetConnectedRegionKey() == KF_LINKS_HOUSE) {
|
||||
return age == AGE_ADULT;
|
||||
} else if (type == EntranceType::Spawn && entrance->GetConnectedRegionKey() == TEMPLE_OF_TIME) {
|
||||
return age == AGE_CHILD;
|
||||
}
|
||||
|
||||
// Other entrances such as Interior, Dungeon or Grotto are fine unless they have a parent which is one of the above
|
||||
// cases Recursively check parent entrances to verify that they are also not reachable as the wrong age
|
||||
auto& parentEntrances = entrance->GetParentRegion()->entrances;
|
||||
for (Entrance* parentEntrance : parentEntrances) {
|
||||
|
||||
// if parentEntrance is in alreadyChecked, then continue
|
||||
if (ElementInContainer(parentEntrance, alreadyChecked)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool unreachable = EntranceUnreachableAs(parentEntrance, age, alreadyChecked);
|
||||
if (!unreachable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||
SPDLOG_INFO("Validating world\n");
|
||||
|
||||
//check certain conditions when certain types of ER are enabled
|
||||
EntranceType type = EntranceType::None;
|
||||
if (entrancePlaced != nullptr) {
|
||||
type = entrancePlaced->GetType();
|
||||
}
|
||||
|
||||
bool checkPoeCollectorAccess = (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)) && (entrancePlaced == nullptr /*|| Settings::MixedEntrancePools.IsNot(MIXEDENTRANCES_OFF)*/ ||
|
||||
type == EntranceType::Interior || type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn || type == EntranceType::WarpSong || type == EntranceType::OwlDrop);
|
||||
bool checkOtherEntranceAccess = (Settings::ShuffleOverworldEntrances || Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL) /*|| Settings::ShuffleOverworldSpawns*/) && (entrancePlaced == nullptr /*|| Settings::MixedEntrancePools.IsNot(MIXEDENTRANCES_OFF)*/ ||
|
||||
type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn || type == EntranceType::WarpSong || type == EntranceType::OwlDrop);
|
||||
|
||||
// Check to make sure all locations are still reachable
|
||||
Logic::LogicReset();
|
||||
GetAccessibleLocations({}, SearchMode::ValidateWorld, "", checkPoeCollectorAccess, checkOtherEntranceAccess);
|
||||
|
||||
// if not world.decouple_entrances:
|
||||
// Unless entrances are decoupled, we don't want the player to end up through certain entrances as the wrong age
|
||||
// This means we need to hard check that none of the relevant entrances are ever reachable as that age
|
||||
// This is mostly relevant when mixing entrance pools or shuffling special interiors (such as windmill or kak potion shop)
|
||||
// Warp Songs and Overworld Spawns can also end up inside certain indoors so those need to be handled as well
|
||||
std::array<std::string, 2> childForbidden = {"OGC Great Fairy Fountain -> Castle Grounds", "GV Carpenter Tent -> GV Fortress Side"};
|
||||
std::array<std::string, 2> adultForbidden = {"HC Great Fairy Fountain -> Castle Grounds", "HC Storms Grotto -> Castle Grounds"};
|
||||
|
||||
auto allShuffleableEntrances = GetShuffleableEntrances(EntranceType::All, false);
|
||||
for (auto& entrance: allShuffleableEntrances) {
|
||||
|
||||
std::vector<Entrance*> alreadyChecked = {};
|
||||
|
||||
if (entrance->IsShuffled()) {
|
||||
if (entrance->GetReplacement() != nullptr) {
|
||||
|
||||
auto replacementName = entrance->GetReplacement()->GetName();
|
||||
alreadyChecked.push_back(entrance->GetReplacement()->GetReverse());
|
||||
|
||||
if (ElementInContainer(replacementName, childForbidden) && !EntranceUnreachableAs(entrance, AGE_CHILD, alreadyChecked)) {
|
||||
auto message = replacementName + " is replaced by an entrance with a potential child access\n";
|
||||
SPDLOG_INFO(message);
|
||||
return false;
|
||||
} else if (ElementInContainer(replacementName, adultForbidden) && !EntranceUnreachableAs(entrance, AGE_ADULT, alreadyChecked)) {
|
||||
auto message = replacementName + " is replaced by an entrance with a potential adult access\n";
|
||||
SPDLOG_INFO(message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto name = entrance->GetName();
|
||||
alreadyChecked.push_back(entrance->GetReverse());
|
||||
|
||||
if (ElementInContainer(name, childForbidden) && !EntranceUnreachableAs(entrance, AGE_CHILD, alreadyChecked)) {
|
||||
auto message = name + " is potentially accessible as child\n";
|
||||
SPDLOG_INFO(message);
|
||||
return false;
|
||||
} else if (ElementInContainer(name, adultForbidden) && !EntranceUnreachableAs(entrance, AGE_ADULT, alreadyChecked)) {
|
||||
auto message = name + " is potentially accessible as adult\n";
|
||||
SPDLOG_INFO(message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings::ShuffleInteriorEntrances.IsNot(SHUFFLEINTERIORS_OFF) && Settings::GossipStoneHints.IsNot(HINTS_NO_HINTS) &&
|
||||
(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 message = "Kak Impas House entrances are not in the same hint area\n";
|
||||
SPDLOG_INFO(message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If all locations aren't reachable, that means that one of the conditions failed when searching
|
||||
if (!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()) {
|
||||
SPDLOG_INFO("Invalid starting area\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that a region where time passes is always reachable as both ages without having collected any items
|
||||
if (!Areas::HasTimePassAccess(AGE_CHILD) || !Areas::HasTimePassAccess(AGE_ADULT)) {
|
||||
SPDLOG_INFO("Time passing is not guaranteed as both ages\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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()) {
|
||||
SPDLOG_INFO("Path to Temple of Time as adult is not guaranteed\n");
|
||||
return false;
|
||||
} else if (Settings::ResolvedStartingAge == AGE_ADULT && !AreaTable(TEMPLE_OF_TIME)->Child()) {
|
||||
SPDLOG_INFO("Path to Temple of Time as child is not guaranteed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 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()) {
|
||||
SPDLOG_INFO("Big Poe Shop access is not guarenteed as adult\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
SPDLOG_INFO("All Locations NOT REACHABLE\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ReplaceEntrance(Entrance* entrance, Entrance* target, std::vector<EntrancePair>& rollbacks) {
|
||||
|
||||
if (!AreEntrancesCompatible(entrance, target, rollbacks)) {
|
||||
return false;
|
||||
}
|
||||
ChangeConnections(entrance, target);
|
||||
if (ValidateWorld(entrance)) {
|
||||
#ifdef ENABLE_DEBUG
|
||||
std::string ticks = std::to_string(svcGetSystemTick());
|
||||
auto message = "Dumping World Graph at " + ticks + "\n";
|
||||
//PlacementLog_Msg(message);
|
||||
//Areas::DumpWorldGraph(ticks);
|
||||
#endif
|
||||
rollbacks.push_back(EntrancePair{entrance, target});
|
||||
curNumRandomizedEntrances++;
|
||||
DisplayEntranceProgress();
|
||||
return true;
|
||||
} else {
|
||||
#ifdef ENABLE_DEBUG
|
||||
std::string ticks = std::to_string(svcGetSystemTick());
|
||||
auto message = "Dumping World Graph at " + ticks + "\n";
|
||||
//PlacementLog_Msg(message);
|
||||
//Areas::DumpWorldGraph(ticks);
|
||||
#endif
|
||||
if (entrance->GetConnectedRegionKey() != NONE) {
|
||||
RestoreConnections(entrance, target);
|
||||
}
|
||||
}
|
||||
DisplayEntranceProgress();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Shuffle entrances by placing them instead of entrances in the provided target entrances list
|
||||
static bool ShuffleEntrances(std::vector<Entrance*>& entrances, std::vector<Entrance*>& targetEntrances, std::vector<EntrancePair>& rollbacks) {
|
||||
|
||||
Shuffle(entrances);
|
||||
|
||||
//place all entrances in the pool, validating after every placement
|
||||
for (Entrance* entrance : entrances) {
|
||||
if (entrance->GetConnectedRegionKey() != NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Shuffle(targetEntrances);
|
||||
for (Entrance* target : targetEntrances) {
|
||||
if (target->GetConnectedRegionKey() == NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ReplaceEntrance(entrance, target, rollbacks)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entrance->GetConnectedRegionKey() == NONE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//all entrances were validly connected
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ShuffleEntrancePool(std::vector<Entrance*>& entrancePool, std::vector<Entrance*>& targetEntrances) {
|
||||
noRandomEntrances = false;
|
||||
|
||||
auto splitEntrances = SplitEntrancesByRequirements(entrancePool, targetEntrances);
|
||||
|
||||
auto& restrictiveEntrances = splitEntrances[0];
|
||||
auto& softEntrances = splitEntrances[1];
|
||||
|
||||
int retries = 20;
|
||||
while (retries > 0) {
|
||||
if (retries != 20) {
|
||||
#ifdef ENABLE_DEBUG
|
||||
std::string ticks = std::to_string(svcGetSystemTick());
|
||||
auto message = "Failed to connect entrances. Retrying " + std::to_string(retries) + " more times.\nDumping World Graph at " + ticks + "\n";
|
||||
PlacementLog_Msg(message);
|
||||
Areas::DumpWorldGraph(ticks);
|
||||
#endif
|
||||
}
|
||||
retries--;
|
||||
|
||||
std::vector<EntrancePair> rollbacks = {};
|
||||
|
||||
//Shuffle Restrictive Entrances first while more regions are available in
|
||||
//order to heavily reduce the chances of the placement failing
|
||||
bool success = ShuffleEntrances(restrictiveEntrances, targetEntrances, rollbacks);
|
||||
if (success) {
|
||||
success = ShuffleEntrances(softEntrances, targetEntrances, rollbacks);
|
||||
if(!success) {
|
||||
for (auto& pair : rollbacks) {
|
||||
RestoreConnections(pair.first, pair.second);
|
||||
curNumRandomizedEntrances--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
for (auto& pair : rollbacks) {
|
||||
RestoreConnections(pair.first, pair.second);
|
||||
curNumRandomizedEntrances--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//If there are no issues, log the connections and continue
|
||||
for (auto& pair : rollbacks) {
|
||||
ConfirmReplacement(pair.first, pair.second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (retries <= 0) {
|
||||
SPDLOG_INFO("Entrance placement attempt count exceeded. Restarting randomization completely");
|
||||
entranceShuffleFailure = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Process for setting up the shuffling of all entrances to be shuffled
|
||||
int ShuffleAllEntrances() {
|
||||
|
||||
totalRandomizableEntrances = 0;
|
||||
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, 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_GROUNDS, GANONS_CASTLE_ENTRYWAY, 0x0467},
|
||||
{EntranceType::GanonDungeon, GANONS_CASTLE_ENTRYWAY, GANONS_CASTLE_GROUNDS, 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::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}},
|
||||
|
||||
// Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the
|
||||
// grottoLoadTable in src/grotto.c
|
||||
// Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the
|
||||
// grottoReturnTable in src/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}},
|
||||
|
||||
// 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}},
|
||||
|
||||
{{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}},
|
||||
};
|
||||
|
||||
entranceShuffleFailure = false;
|
||||
SetAllEntrancesData(entranceShuffleTable);
|
||||
|
||||
// one_way_entrance_pools = OrderedDict()
|
||||
std::map<EntranceType, std::vector<Entrance*>> entrancePools = {};
|
||||
// one_way_priorities = {}
|
||||
|
||||
//owl drops
|
||||
|
||||
//spawns
|
||||
|
||||
//warpsongs
|
||||
|
||||
//Shuffle Dungeon Entrances
|
||||
if (Settings::ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF)) {
|
||||
entrancePools[EntranceType::Dungeon] = GetShuffleableEntrances(EntranceType::Dungeon);
|
||||
//Add Ganon's Castle, if set to On + Ganon
|
||||
if (Settings::ShuffleDungeonEntrances.Is(SHUFFLEDUNGEONS_GANON)) {
|
||||
AddElementsToPool(entrancePools[EntranceType::Dungeon], GetShuffleableEntrances(EntranceType::GanonDungeon));
|
||||
}
|
||||
//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;});
|
||||
}
|
||||
|
||||
//decoupled entrances stuff
|
||||
}
|
||||
|
||||
//interior entrances
|
||||
if (Settings::ShuffleInteriorEntrances.IsNot(SHUFFLEINTERIORS_OFF)) {
|
||||
entrancePools[EntranceType::Interior] = GetShuffleableEntrances(EntranceType::Interior);
|
||||
//special interiors
|
||||
if (Settings::ShuffleInteriorEntrances.Is(SHUFFLEINTERIORS_ALL)) {
|
||||
AddElementsToPool(entrancePools[EntranceType::Interior], GetShuffleableEntrances(EntranceType::SpecialInterior));
|
||||
}
|
||||
|
||||
//decoupled entrance stuff
|
||||
}
|
||||
|
||||
//grotto entrances
|
||||
if (Settings::ShuffleGrottoEntrances) {
|
||||
entrancePools[EntranceType::GrottoGrave] = GetShuffleableEntrances(EntranceType::GrottoGrave);
|
||||
|
||||
//decoupled entrance stuff
|
||||
}
|
||||
|
||||
//overworld entrances
|
||||
if (Settings::ShuffleOverworldEntrances) {
|
||||
bool excludeOverworldReverse = false; //mix_entrance_pools == all && !decouple_entrances
|
||||
entrancePools[EntranceType::Overworld] = GetShuffleableEntrances(EntranceType::Overworld, excludeOverworldReverse);
|
||||
// if not worlds[0].decouple_entrances:
|
||||
// entrance_pools['Overworld'].remove(world.get_entrance('GV Lower Stream -> Lake Hylia'))
|
||||
if (!excludeOverworldReverse) {
|
||||
totalRandomizableEntrances -= 26; //Only count each overworld entrance once
|
||||
}
|
||||
}
|
||||
|
||||
//Set shuffled entrances as such
|
||||
for (auto& pool : entrancePools) {
|
||||
for (Entrance* entrance : pool.second) {
|
||||
entrance->SetAsShuffled();
|
||||
totalRandomizableEntrances++;
|
||||
if (entrance->GetReverse() != nullptr) {
|
||||
entrance->GetReverse()->SetAsShuffled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//combine entrance pools if mixing pools
|
||||
|
||||
//Build target entrance pools and set the assumption for entrances being reachable
|
||||
//one way entrance stuff
|
||||
|
||||
//assume entrance pools for each type
|
||||
std::map<EntranceType, std::vector<Entrance*>> targetEntrancePools = {};
|
||||
for (auto& pool : entrancePools) {
|
||||
targetEntrancePools[pool.first] = AssumeEntrancePool(pool.second);
|
||||
}
|
||||
|
||||
//distribution stuff
|
||||
|
||||
//check placed on-way entrances
|
||||
//remove replaced entrances so we don't place two in one target
|
||||
//remvoe priority targets if any placed entrances point at their regions
|
||||
|
||||
//place priority entrances
|
||||
|
||||
//delete all targets that we just placed from one way target pools so multiple one way entrances don't use the same target
|
||||
|
||||
//shuffle all entrances among pools to shuffle
|
||||
for (auto& pool : entrancePools) {
|
||||
ShuffleEntrancePool(pool.second, targetEntrancePools[pool.first]);
|
||||
if (entranceShuffleFailure) {
|
||||
return ENTRANCE_SHUFFLE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return ENTRANCE_SHUFFLE_SUCCESS;
|
||||
}
|
||||
|
||||
//Create the set of entrances that will be overridden
|
||||
void CreateEntranceOverrides() {
|
||||
entranceOverrides.clear();
|
||||
if (noRandomEntrances) {
|
||||
return;
|
||||
}
|
||||
SPDLOG_INFO("\nCREATING ENTRANCE OVERRIDES\n");
|
||||
auto allShuffleableEntrances = GetShuffleableEntrances(EntranceType::All, false);
|
||||
|
||||
for (Entrance* entrance : allShuffleableEntrances) {
|
||||
|
||||
//Double-check to make sure the entrance is actually shuffled
|
||||
if (!entrance->IsShuffled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto message = "Setting " + entrance->to_string() + "\n";
|
||||
SPDLOG_INFO(message);
|
||||
|
||||
int16_t originalIndex = entrance->GetIndex();
|
||||
int16_t destinationIndex = entrance->GetReverse()->GetIndex();
|
||||
int16_t originalBlueWarp = entrance->GetBlueWarp();
|
||||
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
||||
int16_t replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
||||
|
||||
entranceOverrides.push_back({
|
||||
.index = originalIndex,
|
||||
.destination = destinationIndex,
|
||||
.blueWarp = originalBlueWarp,
|
||||
.override = replacementIndex,
|
||||
.overrideDestination = replacementDestinationIndex,
|
||||
});
|
||||
|
||||
message = "\tOriginal: " + std::to_string(originalIndex) + "\n";
|
||||
SPDLOG_INFO(message);
|
||||
message = "\tReplacement " + std::to_string(replacementIndex) + "\n";
|
||||
SPDLOG_INFO(message);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::list<Entrance*>> playthroughEntrances;
|
320
soh/soh/Enhancements/randomizer/3drando/entrance.hpp
Normal file
320
soh/soh/Enhancements/randomizer/3drando/entrance.hpp
Normal file
@ -0,0 +1,320 @@
|
||||
#pragma once
|
||||
|
||||
#include "keys.hpp"
|
||||
#include "location_access.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#define ENTRANCE_SHUFFLE_SUCCESS 0
|
||||
#define ENTRANCE_SHUFFLE_FAILURE 1
|
||||
|
||||
|
||||
typedef struct {
|
||||
int16_t index;
|
||||
int16_t destination;
|
||||
int16_t blueWarp;
|
||||
int16_t override;
|
||||
int16_t overrideDestination;
|
||||
} EntranceOverride;
|
||||
|
||||
typedef enum {
|
||||
ENTRANCE_GROUP_NO_GROUP,
|
||||
ENTRANCE_GROUP_KOKIRI_FOREST,
|
||||
ENTRANCE_GROUP_LOST_WOODS,
|
||||
ENTRANCE_GROUP_KAKARIKO,
|
||||
ENTRANCE_GROUP_GRAVEYARD,
|
||||
ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL,
|
||||
ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER,
|
||||
ENTRANCE_GROUP_GORON_CITY,
|
||||
ENTRANCE_GROUP_ZORAS_DOMAIN,
|
||||
ENTRANCE_GROUP_HYRULE_FIELD,
|
||||
ENTRANCE_GROUP_LON_LON_RANCH,
|
||||
ENTRANCE_GROUP_LAKE_HYLIA,
|
||||
ENTRANCE_GROUP_GERUDO_VALLEY,
|
||||
ENTRANCE_GROUP_HAUNTED_WASTELAND,
|
||||
ENTRANCE_GROUP_MARKET,
|
||||
ENTRANCE_GROUP_HYRULE_CASTLE,
|
||||
SPOILER_ENTRANCE_GROUP_COUNT,
|
||||
} SpoilerEntranceGroup;
|
||||
|
||||
typedef enum {
|
||||
ENTRANCE_TYPE_OVERWORLD,
|
||||
ENTRANCE_TYPE_INTERIOR,
|
||||
ENTRANCE_TYPE_GROTTO,
|
||||
ENTRANCE_TYPE_DUNGEON,
|
||||
ENTRANCE_TYPE_COUNT,
|
||||
} TrackerEntranceType;
|
||||
|
||||
typedef struct {
|
||||
int16_t index;
|
||||
char* name;
|
||||
SpoilerEntranceGroup group;
|
||||
TrackerEntranceType type;
|
||||
uint8_t oneExit;
|
||||
} EntranceData;
|
||||
|
||||
typedef struct {
|
||||
uint8_t EntranceCount;
|
||||
uint16_t GroupEntranceCounts[SPOILER_ENTRANCE_GROUP_COUNT];
|
||||
uint16_t GroupOffsets[SPOILER_ENTRANCE_GROUP_COUNT];
|
||||
} EntranceTrackingData;
|
||||
|
||||
extern std::list<EntranceOverride> entranceOverrides;
|
||||
|
||||
enum class EntranceType {
|
||||
None,
|
||||
OwlDrop,
|
||||
Spawn,
|
||||
WarpSong,
|
||||
Dungeon,
|
||||
GanonDungeon,
|
||||
Interior,
|
||||
SpecialInterior,
|
||||
GrottoGrave,
|
||||
Overworld,
|
||||
Extra,
|
||||
All,
|
||||
};
|
||||
|
||||
class Entrance {
|
||||
public:
|
||||
|
||||
Entrance(uint32_t connectedRegion_, std::vector<ConditionFn> conditions_met_)
|
||||
: connectedRegion(connectedRegion_) {
|
||||
conditions_met.resize(2);
|
||||
for (size_t i = 0; i < conditions_met_.size(); i++) {
|
||||
conditions_met[i] = conditions_met_[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool GetConditionsMet() const {
|
||||
if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
return true;
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHLESS)) {
|
||||
return conditions_met[0]();
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHED)) {
|
||||
if (conditions_met[0]()) {
|
||||
return true;
|
||||
} else if (conditions_met[1] != NULL) {
|
||||
return conditions_met[1]();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string to_string() const {
|
||||
return AreaTable(parentRegion)->regionName + " -> " + AreaTable(connectedRegion)->regionName;
|
||||
}
|
||||
|
||||
void SetName(std::string name_ = "") {
|
||||
if (name_ == "") {
|
||||
name = AreaTable(parentRegion)->regionName + " -> " + AreaTable(connectedRegion)->regionName;
|
||||
} else {
|
||||
name = std::move(name_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string GetName() const {
|
||||
return name;
|
||||
}
|
||||
|
||||
void printAgeTimeAccess() {
|
||||
CitraPrint("Name: ");
|
||||
CitraPrint(name);
|
||||
auto message = "Child Day: " + std::to_string(CheckConditionAtAgeTime(Logic::IsChild, Logic::AtDay)) + "\t"
|
||||
"Child Night: " + std::to_string(CheckConditionAtAgeTime(Logic::IsChild, Logic::AtNight)) + "\t"
|
||||
"Adult Day: " + std::to_string(CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtDay)) + "\t"
|
||||
"Adult Night: " + std::to_string(CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtNight));
|
||||
CitraPrint(message);
|
||||
}
|
||||
|
||||
bool ConditionsMet(bool allAgeTimes = false) const {
|
||||
|
||||
Area* parent = AreaTable(parentRegion);
|
||||
int conditionsMet = 0;
|
||||
|
||||
if (allAgeTimes && !parent->AllAccess()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check all possible day/night condition combinations
|
||||
conditionsMet = (parent->childDay && CheckConditionAtAgeTime(Logic::IsChild, Logic::AtDay, allAgeTimes)) +
|
||||
(parent->childNight && CheckConditionAtAgeTime(Logic::IsChild, Logic::AtNight, allAgeTimes)) +
|
||||
(parent->adultDay && CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtDay, allAgeTimes)) +
|
||||
(parent->adultNight && CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtNight, allAgeTimes));
|
||||
|
||||
return conditionsMet && (!allAgeTimes || conditionsMet == 4);
|
||||
}
|
||||
|
||||
uint32_t Getuint32_t() const {
|
||||
return connectedRegion;
|
||||
}
|
||||
|
||||
//set the logic to be a specific age and time of day and see if the condition still holds
|
||||
bool CheckConditionAtAgeTime(bool& age, bool& time, bool passAnyway = false) const {
|
||||
|
||||
Logic::IsChild = false;
|
||||
Logic::IsAdult = false;
|
||||
Logic::AtDay = false;
|
||||
Logic::AtNight = false;
|
||||
|
||||
time = true;
|
||||
age = true;
|
||||
|
||||
Logic::UpdateHelpers();
|
||||
return GetConditionsMet() && (connectedRegion != NONE || passAnyway);
|
||||
}
|
||||
|
||||
uint32_t GetConnectedRegionKey() const {
|
||||
return connectedRegion;
|
||||
}
|
||||
|
||||
Area* GetConnectedRegion() const {
|
||||
return AreaTable(connectedRegion);
|
||||
}
|
||||
|
||||
void SetParentRegion(uint32_t newParent) {
|
||||
parentRegion = newParent;
|
||||
}
|
||||
|
||||
uint32_t GetParentRegionKey() const {
|
||||
return parentRegion;
|
||||
}
|
||||
|
||||
Area* GetParentRegion() const {
|
||||
return AreaTable(parentRegion);
|
||||
}
|
||||
|
||||
void SetNewEntrance(uint32_t newRegion) {
|
||||
connectedRegion = newRegion;
|
||||
}
|
||||
|
||||
void SetAsShuffled() {
|
||||
shuffled = true;
|
||||
}
|
||||
|
||||
bool IsShuffled() const {
|
||||
return shuffled;
|
||||
}
|
||||
|
||||
bool IsAddedToPool() const {
|
||||
return addedToPool;
|
||||
}
|
||||
|
||||
void AddToPool() {
|
||||
addedToPool = true;
|
||||
}
|
||||
|
||||
void RemoveFromPool() {
|
||||
addedToPool = false;
|
||||
}
|
||||
|
||||
void SetAsPrimary() {
|
||||
primary = true;
|
||||
}
|
||||
|
||||
bool IsPrimary() const {
|
||||
return primary;
|
||||
}
|
||||
|
||||
int16_t GetIndex() const {
|
||||
return index;
|
||||
}
|
||||
|
||||
void SetIndex(int16_t newIndex) {
|
||||
index = newIndex;
|
||||
}
|
||||
|
||||
int16_t GetBlueWarp() const {
|
||||
return blueWarp;
|
||||
}
|
||||
|
||||
void SetBlueWarp(int16_t newBlueWarp) {
|
||||
blueWarp = newBlueWarp;
|
||||
}
|
||||
|
||||
Entrance* GetAssumed() const {
|
||||
return assumed;
|
||||
}
|
||||
|
||||
void SetReplacement(Entrance* newReplacement) {
|
||||
replacement = newReplacement;
|
||||
}
|
||||
|
||||
Entrance* GetReplacement() const {
|
||||
return replacement;
|
||||
}
|
||||
|
||||
EntranceType GetType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
void SetType(EntranceType newType) {
|
||||
type = newType;
|
||||
}
|
||||
|
||||
Entrance* GetReverse() const {
|
||||
return reverse;
|
||||
}
|
||||
|
||||
void Connect(uint32_t newConnectedRegion) {
|
||||
connectedRegion = newConnectedRegion;
|
||||
AreaTable(newConnectedRegion)->entrances.push_front(this);
|
||||
}
|
||||
|
||||
uint32_t Disconnect() {
|
||||
AreaTable(connectedRegion)->entrances.remove_if([this](const auto entrance){return this == entrance;});
|
||||
uint32_t previouslyConnected = connectedRegion;
|
||||
connectedRegion = NONE;
|
||||
return previouslyConnected;
|
||||
}
|
||||
|
||||
void BindTwoWay(Entrance* otherEntrance) {
|
||||
reverse = otherEntrance;
|
||||
otherEntrance->reverse = this;
|
||||
}
|
||||
|
||||
Entrance* GetNewTarget() {
|
||||
AreaTable(ROOT)->AddExit(ROOT, connectedRegion, []{return true;});
|
||||
Entrance* targetEntrance = AreaTable(ROOT)->GetExit(connectedRegion);
|
||||
targetEntrance->SetReplacement(this);
|
||||
targetEntrance->SetName(GetParentRegion()->regionName + " -> " + GetConnectedRegion()->regionName);
|
||||
return targetEntrance;
|
||||
}
|
||||
|
||||
Entrance* AssumeReachable() {
|
||||
if (assumed == nullptr) {
|
||||
assumed = GetNewTarget();
|
||||
Disconnect();
|
||||
}
|
||||
return assumed;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t parentRegion;
|
||||
uint32_t connectedRegion;
|
||||
std::vector<ConditionFn> conditions_met;
|
||||
|
||||
//Entrance Randomizer stuff
|
||||
EntranceType type = EntranceType::None;
|
||||
Entrance* target = nullptr;
|
||||
Entrance* reverse = nullptr;
|
||||
Entrance* assumed = nullptr;
|
||||
Entrance* replacement = nullptr;
|
||||
int16_t index = 0xFFFF;
|
||||
int16_t blueWarp = 0;
|
||||
bool shuffled = false;
|
||||
bool primary = false;
|
||||
bool addedToPool = false;
|
||||
std::string name = "";
|
||||
};
|
||||
|
||||
int ShuffleAllEntrances();
|
||||
void CreateEntranceOverrides();
|
||||
EntranceTrackingData* GetEntranceTrackingData();
|
||||
|
||||
extern std::vector<std::list<Entrance*>> playthroughEntrances;
|
||||
extern bool noRandomEntrances;
|
1074
soh/soh/Enhancements/randomizer/3drando/fill.cpp
Normal file
1074
soh/soh/Enhancements/randomizer/3drando/fill.cpp
Normal file
File diff suppressed because it is too large
Load Diff
27
soh/soh/Enhancements/randomizer/3drando/fill.hpp
Normal file
27
soh/soh/Enhancements/randomizer/3drando/fill.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "keys.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
enum class SearchMode {
|
||||
ReachabilitySearch,
|
||||
GeneratePlaythrough,
|
||||
CheckBeatable,
|
||||
AllLocationsReachable,
|
||||
ValidateWorld,
|
||||
TimePassAccess,
|
||||
TempleOfTimeAccess,
|
||||
ValidStartingRegion,
|
||||
PoeCollectorAccess,
|
||||
};
|
||||
|
||||
void ClearProgress();
|
||||
void VanillaFill();
|
||||
int Fill();
|
||||
|
||||
std::vector<uint32_t> GetAccessibleLocations(const std::vector<uint32_t>& allowedLocations,
|
||||
SearchMode mode = SearchMode::ReachabilitySearch, std::string ignore = "",
|
||||
bool checkPoeCollectorAccess = false,
|
||||
bool checkOtherEntranceAccess = false);
|
2268
soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
Normal file
2268
soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
Normal file
File diff suppressed because it is too large
Load Diff
16
soh/soh/Enhancements/randomizer/3drando/hint_list.hpp
Normal file
16
soh/soh/Enhancements/randomizer/3drando/hint_list.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "hints.hpp"
|
||||
#include "keys.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
extern std::array<HintText, KEY_ENUM_MAX> hintTable;
|
||||
|
||||
void HintTable_Init();
|
||||
const HintText& Hint(uint32_t hintKey);
|
||||
std::vector<HintText> GetHintCategory(HintCategory category);
|
||||
|
||||
void HintTable_Init_Item();
|
||||
void HintTable_Init_Exclude_Overworld();
|
||||
void HintTable_Init_Exclude_Dungeon();
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1952
soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp
Normal file
1952
soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp
Normal file
File diff suppressed because it is too large
Load Diff
878
soh/soh/Enhancements/randomizer/3drando/hints.cpp
Normal file
878
soh/soh/Enhancements/randomizer/3drando/hints.cpp
Normal file
@ -0,0 +1,878 @@
|
||||
#include "hints.hpp"
|
||||
|
||||
#include "custom_messages.hpp"
|
||||
#include "dungeon.hpp"
|
||||
#include "item_location.hpp"
|
||||
#include "item_pool.hpp"
|
||||
#include "logic.hpp"
|
||||
#include "random.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "fill.hpp"
|
||||
#include "hint_list.hpp"
|
||||
#include "trial.hpp"
|
||||
#include "entrance.hpp"
|
||||
#include "z64item.h"
|
||||
#include <Lib/spdlog/include/spdlog/spdlog.h>
|
||||
|
||||
using namespace CustomMessages;
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
using namespace Trial;
|
||||
|
||||
constexpr std::array<HintSetting, 4> hintSettingTable{{
|
||||
// Useless hints
|
||||
{
|
||||
.dungeonsWothLimit = 2,
|
||||
.dungeonsBarrenLimit = 1,
|
||||
.namedItemsRequired = false,
|
||||
.distTable = {{
|
||||
{.type = HintType::Trial, .order = 1, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Always, .order = 2, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Woth, .order = 3, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Barren, .order = 4, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Entrance, .order = 5, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Sometimes, .order = 6, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Random, .order = 7, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Item, .order = 8, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Song, .order = 9, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Overworld, .order = 10, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Dungeon, .order = 11, .weight = 0, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::Junk, .order = 12, .weight = 99, .fixed = 0, .copies = 0},
|
||||
{.type = HintType::NamedItem, .order = 13, .weight = 0, .fixed = 0, .copies = 0},
|
||||
}},
|
||||
},
|
||||
|
||||
// Balanced hints
|
||||
{
|
||||
.dungeonsWothLimit = 2,
|
||||
.dungeonsBarrenLimit = 1,
|
||||
.namedItemsRequired = true,
|
||||
.distTable = {{
|
||||
{.type = HintType::Trial, .order = 1, .weight = 0, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Always, .order = 2, .weight = 0, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Woth, .order = 3, .weight = 7, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Barren, .order = 4, .weight = 4, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Entrance, .order = 5, .weight = 6, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Sometimes, .order = 6, .weight = 0, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Random, .order = 7, .weight = 12, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Item, .order = 8, .weight = 10, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Song, .order = 9, .weight = 2, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Overworld, .order = 10, .weight = 4, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Dungeon, .order = 11, .weight = 3, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Junk, .order = 12, .weight = 6, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::NamedItem, .order = 13, .weight = 0, .fixed = 0, .copies = 1},
|
||||
}},
|
||||
},
|
||||
|
||||
// Strong hints
|
||||
{
|
||||
.dungeonsWothLimit = 2,
|
||||
.dungeonsBarrenLimit = 1,
|
||||
.namedItemsRequired = true,
|
||||
.distTable = {{
|
||||
{.type = HintType::Trial, .order = 1, .weight = 0, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Always, .order = 2, .weight = 0, .fixed = 0, .copies = 2},
|
||||
{.type = HintType::Woth, .order = 3, .weight = 12, .fixed = 0, .copies = 2},
|
||||
{.type = HintType::Barren, .order = 4, .weight = 12, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Entrance, .order = 5, .weight = 4, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Sometimes, .order = 6, .weight = 0, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Random, .order = 7, .weight = 8, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Item, .order = 8, .weight = 8, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Song, .order = 9, .weight = 4, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Overworld, .order = 10, .weight = 6, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Dungeon, .order = 11, .weight = 6, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Junk, .order = 12, .weight = 0, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::NamedItem, .order = 13, .weight = 0, .fixed = 0, .copies = 1},
|
||||
}},
|
||||
},
|
||||
|
||||
// Very strong hints
|
||||
{
|
||||
.dungeonsWothLimit = 40,
|
||||
.dungeonsBarrenLimit = 40,
|
||||
.namedItemsRequired = true,
|
||||
.distTable = {{
|
||||
{.type = HintType::Trial, .order = 1, .weight = 0, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Always, .order = 2, .weight = 0, .fixed = 0, .copies = 2},
|
||||
{.type = HintType::Woth, .order = 3, .weight = 15, .fixed = 0, .copies = 2},
|
||||
{.type = HintType::Barren, .order = 4, .weight = 15, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Entrance, .order = 5, .weight = 10, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Sometimes, .order = 6, .weight = 0, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Random, .order = 7, .weight = 0, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Item, .order = 8, .weight = 5, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Song, .order = 9, .weight = 2, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Overworld, .order = 10, .weight = 7, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Dungeon, .order = 11, .weight = 7, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::Junk, .order = 12, .weight = 0, .fixed = 0, .copies = 1},
|
||||
{.type = HintType::NamedItem, .order = 13, .weight = 0, .fixed = 0, .copies = 1},
|
||||
}},
|
||||
},
|
||||
}};
|
||||
|
||||
std::array<DungeonInfo, 10> dungeonInfoData;
|
||||
|
||||
Text childAltarText;
|
||||
Text adultAltarText;
|
||||
Text ganonText;
|
||||
Text ganonHintText;
|
||||
|
||||
Text& GetChildAltarText() {
|
||||
return childAltarText;
|
||||
}
|
||||
|
||||
Text& GetAdultAltarText() {
|
||||
return adultAltarText;
|
||||
}
|
||||
|
||||
Text& GetGanonText() {
|
||||
return ganonText;
|
||||
}
|
||||
|
||||
Text& GetGanonHintText() {
|
||||
return ganonHintText;
|
||||
}
|
||||
|
||||
static Area* GetHintRegion(const uint32_t area) {
|
||||
|
||||
std::vector<uint32_t> alreadyChecked = {};
|
||||
std::vector<uint32_t> spotQueue = {area};
|
||||
|
||||
while (!spotQueue.empty()) {
|
||||
uint32_t region = spotQueue.back();
|
||||
alreadyChecked.push_back(region);
|
||||
spotQueue.pop_back();
|
||||
|
||||
if (AreaTable(region)->hintKey != NONE) {
|
||||
return AreaTable(region);
|
||||
}
|
||||
|
||||
//add unchecked entrances to spot queue
|
||||
bool checked = false;
|
||||
for (auto& entrance : AreaTable(region)->entrances) {
|
||||
for (uint32_t checkedEntrance : alreadyChecked) {
|
||||
if (entrance->GetParentRegionKey() == checkedEntrance) {
|
||||
checked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!checked) {
|
||||
spotQueue.insert(spotQueue.begin(), entrance->GetParentRegionKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AreaTable(NONE);
|
||||
}
|
||||
|
||||
uint32_t GetHintRegionHintKey(const uint32_t area) {
|
||||
return GetHintRegion(area)->hintKey;
|
||||
}
|
||||
|
||||
uint32_t GetHintRegionuint32_t(const uint32_t area) {
|
||||
return GetHintRegion(area)->hintKey;
|
||||
}
|
||||
|
||||
uint32_t GetLocationRegionuint32_t(const uint32_t location) {
|
||||
return GetHintRegion(Location(location)->GetParentRegionKey())->hintKey;
|
||||
}
|
||||
|
||||
static std::vector<uint32_t> GetAccessibleGossipStones(const uint32_t hintedLocation = GANON) {
|
||||
//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);
|
||||
|
||||
LogicReset();
|
||||
auto accessibleGossipStones = GetAccessibleLocations(gossipStoneLocations);
|
||||
//Give the item back to the location
|
||||
Location(hintedLocation)->SetPlacedItem(originalItem);
|
||||
|
||||
return accessibleGossipStones;
|
||||
}
|
||||
|
||||
static void AddHint(Text hint, const uint32_t gossipStone, const std::vector<uint8_t>& colors = {}) {
|
||||
//save hints as dummy items for writing to the spoiler log
|
||||
NewItem(gossipStone, Item{hint, ITEMTYPE_EVENT, GI_RUPEE_BLUE_LOSE, false, &noVariable, NONE});
|
||||
Location(gossipStone)->SetPlacedItem(gossipStone);
|
||||
|
||||
//create the in game message
|
||||
// uint32_t messageId = 0x400 + Location(gossipStone)->GetFlag();
|
||||
// uint32_t sariaMessageId = 0xA00 + Location(gossipStone)->GetFlag();
|
||||
// CreateMessageFromTextObject(messageId, 0, 2, 3, AddColorsAndFormat(hint, colors));
|
||||
// CreateMessageFromTextObject(sariaMessageId, 0, 2, 3, AddColorsAndFormat(hint + EVENT_TRIGGER(), colors));
|
||||
}
|
||||
|
||||
static void CreateLocationHint(const std::vector<uint32_t>& possibleHintLocations) {
|
||||
//return if there aren't any hintable locations or gossip stones available
|
||||
if (possibleHintLocations.empty()) {
|
||||
SPDLOG_INFO("\tNO LOCATIONS TO HINT\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t hintedLocation = RandomElement(possibleHintLocations);
|
||||
const std::vector<uint32_t> accessibleGossipStones = GetAccessibleGossipStones(hintedLocation);
|
||||
|
||||
SPDLOG_INFO("\tLocation: ");
|
||||
SPDLOG_INFO(Location(hintedLocation)->GetName());
|
||||
SPDLOG_INFO("\n");
|
||||
|
||||
SPDLOG_INFO("\tItem: ");
|
||||
SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
|
||||
SPDLOG_INFO("\n");
|
||||
|
||||
if (accessibleGossipStones.empty()) {
|
||||
SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t gossipStone = RandomElement(accessibleGossipStones);
|
||||
Location(hintedLocation)->SetAsHinted();
|
||||
|
||||
//make hint text
|
||||
Text locationHintText = Location(hintedLocation)->GetHint().GetText();
|
||||
Text itemHintText = Location(hintedLocation)->GetPlacedItem().GetHint().GetText();
|
||||
Text prefix = Hint(PREFIX).GetText();
|
||||
|
||||
Text finalHint = prefix + locationHintText + " #"+itemHintText+"#.";
|
||||
SPDLOG_INFO("\tMessage: ");
|
||||
SPDLOG_INFO(finalHint.english);
|
||||
SPDLOG_INFO("\n\n");
|
||||
|
||||
AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED});
|
||||
}
|
||||
|
||||
static void CreateWothHint(uint8_t* remainingDungeonWothHints) {
|
||||
// get locations that are in the current playthrough
|
||||
std::vector<uint32_t> 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() &&
|
||||
(*remainingDungeonWothHints) > 0)); // make sure we haven't surpassed the woth dungeon limit
|
||||
});
|
||||
AddElementsToPool(possibleHintLocations, wothHintLocations);
|
||||
|
||||
// If no more locations can be hinted at for woth, then just try to get another hint
|
||||
if (possibleHintLocations.empty()) {
|
||||
SPDLOG_INFO("\tNO LOCATIONS TO HINT\n\n");
|
||||
return;
|
||||
}
|
||||
uint32_t hintedLocation = RandomElement(possibleHintLocations);
|
||||
|
||||
SPDLOG_INFO("\tLocation: ");
|
||||
SPDLOG_INFO(Location(hintedLocation)->GetName());
|
||||
SPDLOG_INFO("\n");
|
||||
|
||||
SPDLOG_INFO("\tItem: ");
|
||||
SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
|
||||
SPDLOG_INFO("\n");
|
||||
|
||||
// get an accessible gossip stone
|
||||
const std::vector<uint32_t> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
|
||||
|
||||
if (gossipStoneLocations.empty()) {
|
||||
SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n");
|
||||
return;
|
||||
}
|
||||
Location(hintedLocation)->SetAsHinted();
|
||||
uint32_t gossipStone = RandomElement(gossipStoneLocations);
|
||||
|
||||
// form hint text
|
||||
Text locationText;
|
||||
if (Location(hintedLocation)->IsDungeon()) {
|
||||
*remainingDungeonWothHints -= 1;
|
||||
uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey();
|
||||
locationText = AreaTable(parentRegion)->GetHint().GetText();
|
||||
|
||||
} else {
|
||||
uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey();
|
||||
locationText = GetHintRegion(parentRegion)->GetHint().GetText();
|
||||
}
|
||||
Text finalWothHint = Hint(PREFIX).GetText() + "#" + locationText + "#" + Hint(WAY_OF_THE_HERO).GetText();
|
||||
SPDLOG_INFO("\tMessage: ");
|
||||
SPDLOG_INFO(finalWothHint.english);
|
||||
SPDLOG_INFO("\n\n");
|
||||
AddHint(finalWothHint, gossipStone, { QM_LBLUE });
|
||||
}
|
||||
|
||||
static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vector<uint32_t>& barrenLocations) {
|
||||
// remove dungeon locations if necessary
|
||||
if (*remainingDungeonBarrenHints < 1) {
|
||||
barrenLocations =
|
||||
FilterFromPool(barrenLocations, [](const uint32_t loc) { return !(Location(loc)->IsDungeon()); });
|
||||
}
|
||||
|
||||
if (barrenLocations.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t hintedLocation = RandomElement(barrenLocations, true);
|
||||
|
||||
SPDLOG_INFO("\tLocation: ");
|
||||
SPDLOG_INFO(Location(hintedLocation)->GetName());
|
||||
SPDLOG_INFO("\n");
|
||||
|
||||
SPDLOG_INFO("\tItem: ");
|
||||
SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
|
||||
SPDLOG_INFO("\n");
|
||||
|
||||
// get an accessible gossip stone
|
||||
const std::vector<uint32_t> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
|
||||
if (gossipStoneLocations.empty()) {
|
||||
SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n");
|
||||
return;
|
||||
}
|
||||
Location(hintedLocation)->SetAsHinted();
|
||||
uint32_t gossipStone = RandomElement(gossipStoneLocations);
|
||||
|
||||
// form hint text
|
||||
Text locationText;
|
||||
if (Location(hintedLocation)->IsDungeon()) {
|
||||
*remainingDungeonBarrenHints -= 1;
|
||||
uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey();
|
||||
locationText = Hint(AreaTable(parentRegion)->hintKey).GetText();
|
||||
} else {
|
||||
uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey();
|
||||
locationText = Hint(GetHintRegion(parentRegion)->hintKey).GetText();
|
||||
}
|
||||
Text finalBarrenHint =
|
||||
Hint(PREFIX).GetText() + Hint(PLUNDERING).GetText() + "#" + locationText + "#" + Hint(FOOLISH).GetText();
|
||||
SPDLOG_INFO("\tMessage: ");
|
||||
SPDLOG_INFO(finalBarrenHint.english);
|
||||
SPDLOG_INFO("\n\n");
|
||||
AddHint(finalBarrenHint, gossipStone, { QM_PINK });
|
||||
|
||||
// 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;
|
||||
});
|
||||
}
|
||||
|
||||
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());
|
||||
});
|
||||
//If no more locations can be hinted at, then just try to get another hint
|
||||
if (possibleHintLocations.empty()) {
|
||||
SPDLOG_INFO("\tNO LOCATIONS TO HINT\n\n");
|
||||
return;
|
||||
}
|
||||
uint32_t hintedLocation = RandomElement(possibleHintLocations);
|
||||
|
||||
SPDLOG_INFO("\tLocation: ");
|
||||
SPDLOG_INFO(Location(hintedLocation)->GetName());
|
||||
SPDLOG_INFO("\n");
|
||||
|
||||
SPDLOG_INFO("\tItem: ");
|
||||
SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish());
|
||||
SPDLOG_INFO("\n");
|
||||
|
||||
//get an acessible gossip stone
|
||||
const std::vector<uint32_t> gossipStoneLocations = GetAccessibleGossipStones(hintedLocation);
|
||||
if (gossipStoneLocations.empty()) {
|
||||
SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n");
|
||||
return;
|
||||
}
|
||||
Location(hintedLocation)->SetAsHinted();
|
||||
uint32_t gossipStone = RandomElement(gossipStoneLocations);
|
||||
|
||||
//form hint text
|
||||
Text itemText = Location(hintedLocation)->GetPlacedItem().GetHint().GetText();
|
||||
if (Location(hintedLocation)->IsDungeon()) {
|
||||
uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey();
|
||||
Text locationText = AreaTable(parentRegion)->GetHint().GetText();
|
||||
Text finalHint = Hint(PREFIX).GetText()+"#"+locationText+"# "+Hint(HOARDS).GetText()+" #"+itemText+"#.";
|
||||
SPDLOG_INFO("\tMessage: ");
|
||||
SPDLOG_INFO(finalHint.english);
|
||||
SPDLOG_INFO("\n\n");
|
||||
AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED});
|
||||
} else {
|
||||
Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText();
|
||||
Text finalHint = Hint(PREFIX).GetText()+"#"+itemText+"# "+Hint(CAN_BE_FOUND_AT).GetText()+" #"+locationText+"#.";
|
||||
SPDLOG_INFO("\tMessage: ");
|
||||
SPDLOG_INFO(finalHint.english);
|
||||
SPDLOG_INFO("\n\n");
|
||||
AddHint(finalHint, gossipStone, {QM_RED, QM_GREEN});
|
||||
}
|
||||
}
|
||||
|
||||
static void CreateGoodItemHint() {
|
||||
CreateRandomLocationHint(true);
|
||||
}
|
||||
|
||||
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);
|
||||
if (gossipStones.empty()) {
|
||||
SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n");
|
||||
return;
|
||||
}
|
||||
uint32_t gossipStone = RandomElement(gossipStones);
|
||||
Text hint = junkHint.GetText();
|
||||
|
||||
SPDLOG_INFO("\tMessage: ");
|
||||
SPDLOG_INFO(hint.english);
|
||||
SPDLOG_INFO("\n\n");
|
||||
|
||||
AddHint(hint, gossipStone, {QM_PINK});
|
||||
}
|
||||
|
||||
static std::vector<uint32_t> CalculateBarrenRegions() {
|
||||
std::vector<uint32_t> barrenLocations = {};
|
||||
std::vector<uint32_t> potentiallyUsefulLocations = {};
|
||||
|
||||
for (uint32_t loc : 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)) {
|
||||
AddElementsToPool(potentiallyUsefulLocations, std::vector{loc});
|
||||
} else {
|
||||
if (loc != LINKS_POCKET) { //Nobody cares to know if Link's Pocket is barren
|
||||
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) {
|
||||
uint32_t barrenKey = GetLocationRegionuint32_t(loc);
|
||||
uint32_t usefulKey = GetLocationRegionuint32_t(usefulLoc);
|
||||
if (barrenKey == usefulKey) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return finalBarrenLocations;
|
||||
}
|
||||
|
||||
static void CreateTrialHints() {
|
||||
//six trials
|
||||
if (RandomGanonsTrials && GanonsTrialsCount.Is(6)) {
|
||||
|
||||
//get a random gossip stone
|
||||
auto gossipStones = GetAccessibleGossipStones();
|
||||
auto gossipStone = RandomElement(gossipStones, false);
|
||||
|
||||
//make hint
|
||||
auto hint = Hint(PREFIX).GetText() + Hint(SIX_TRIALS).GetText();
|
||||
AddHint(hint, gossipStone, {QM_PINK});
|
||||
|
||||
//zero trials
|
||||
} else if (RandomGanonsTrials && GanonsTrialsCount.Is(0)) {
|
||||
|
||||
//get a random gossip stone
|
||||
auto gossipStones = GetAccessibleGossipStones();
|
||||
auto gossipStone = RandomElement(gossipStones, false);
|
||||
|
||||
//make hint
|
||||
auto hint = Hint(PREFIX).GetText() + Hint(ZERO_TRIALS).GetText();
|
||||
AddHint(hint, gossipStone, {QM_YELLOW});
|
||||
|
||||
//4 or 5 required trials
|
||||
} else if (GanonsTrialsCount.Is(5) || GanonsTrialsCount.Is(4)) {
|
||||
|
||||
//get skipped trials
|
||||
std::vector<TrialInfo*> trials = {};
|
||||
trials.assign(trialList.begin(), trialList.end());
|
||||
auto skippedTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsSkipped();});
|
||||
|
||||
//create a hint for each skipped trial
|
||||
for (auto& trial : skippedTrials) {
|
||||
//get a random gossip stone
|
||||
auto gossipStones = GetAccessibleGossipStones();
|
||||
auto gossipStone = RandomElement(gossipStones, false);
|
||||
|
||||
//make hint
|
||||
auto hint = Hint(PREFIX).GetText()+"#"+trial->GetName()+"#"+Hint(FOUR_TO_FIVE_TRIALS).GetText();
|
||||
AddHint(hint, gossipStone, {QM_YELLOW});
|
||||
}
|
||||
//1 to 3 trials
|
||||
} else if (GanonsTrialsCount.Value<uint8_t>() >= 1 && GanonsTrialsCount.Value<uint8_t>() <= 3) {
|
||||
//get requried trials
|
||||
std::vector<TrialInfo*> trials = {};
|
||||
trials.assign(trialList.begin(), trialList.end());
|
||||
auto requiredTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsRequired();});
|
||||
|
||||
//create a hint for each required trial
|
||||
for (auto& trial : requiredTrials) {
|
||||
//get a random gossip stone
|
||||
auto gossipStones = GetAccessibleGossipStones();
|
||||
auto gossipStone = RandomElement(gossipStones, false);
|
||||
|
||||
//make hint
|
||||
auto hint = Hint(PREFIX).GetText()+"#"+trial->GetName()+"#"+Hint(ONE_TO_THREE_TRIALS).GetText();
|
||||
AddHint(hint, gossipStone, {QM_PINK});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CreateGanonText() {
|
||||
|
||||
//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;});
|
||||
|
||||
//If there is no light arrow location, it was in the player's inventory at the start
|
||||
if (lightArrowLocation.empty()) {
|
||||
ganonHintText = Hint(LIGHT_ARROW_LOCATION_HINT).GetText()+Hint(YOUR_POCKET).GetText();
|
||||
} else {
|
||||
ganonHintText = Hint(LIGHT_ARROW_LOCATION_HINT).GetText()+GetHintRegion(Location(lightArrowLocation[0])->GetParentRegionKey())->GetHint().GetText();
|
||||
}
|
||||
ganonHintText = ganonHintText + "!";
|
||||
|
||||
CreateMessageFromTextObject(0x70CC, 0, 2, 3, AddColorsAndFormat(ganonHintText));
|
||||
}
|
||||
|
||||
//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();
|
||||
|
||||
std::string rewardString = "$" + std::to_string(itemKey - KOKIRI_EMERALD);
|
||||
|
||||
// RANDOTODO implement colors for locations
|
||||
return Text()+rewardString+GetHintRegion(Location(location)->GetParentRegionKey())->GetHint().GetText()+"...^";
|
||||
}
|
||||
|
||||
static Text BuildDoorOfTimeText() {
|
||||
std::string itemObtained;
|
||||
Text doorOfTimeText;
|
||||
|
||||
if (OpenDoorOfTime.Is(OPENDOOROFTIME_OPEN)) {
|
||||
itemObtained = "$o";
|
||||
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTOPEN).GetText();
|
||||
|
||||
} else if (OpenDoorOfTime.Is(OPENDOOROFTIME_CLOSED)) {
|
||||
itemObtained = "$c";
|
||||
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTCLOSED).GetText();
|
||||
|
||||
} else if (OpenDoorOfTime.Is(OPENDOOROFTIME_INTENDED)) {
|
||||
itemObtained = "$i";
|
||||
doorOfTimeText = Hint(CHILD_ALTAR_TEXT_END_DOTINTENDED).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) {
|
||||
Text requirement = Hint(req).GetTextCopy();
|
||||
if (count.Value<uint8_t>() == 1) {
|
||||
requirement.SetForm(SINGULAR);
|
||||
} else {
|
||||
requirement.SetForm(PLURAL);
|
||||
}
|
||||
requirement.Replace("%d", std::to_string(count.Value<uint8_t>()));
|
||||
return requirement;
|
||||
}
|
||||
|
||||
static Text BuildBridgeReqsText() {
|
||||
Text bridgeText;
|
||||
|
||||
if (Bridge.Is(RAINBOWBRIDGE_OPEN)) {
|
||||
bridgeText = Hint(BRIDGE_OPEN_HINT).GetText();
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_VANILLA)) {
|
||||
bridgeText = Hint(BRIDGE_VANILLA_HINT).GetText();
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_STONES)) {
|
||||
bridgeText = BuildCountReq(BRIDGE_STONES_HINT, BridgeStoneCount);
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_MEDALLIONS)) {
|
||||
bridgeText = BuildCountReq(BRIDGE_MEDALLIONS_HINT, BridgeMedallionCount);
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_REWARDS)) {
|
||||
bridgeText = BuildCountReq(BRIDGE_REWARDS_HINT, BridgeRewardCount);
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_DUNGEONS)) {
|
||||
bridgeText = BuildCountReq(BRIDGE_DUNGEONS_HINT, BridgeDungeonCount);
|
||||
|
||||
} else if (Bridge.Is(RAINBOWBRIDGE_TOKENS)) {
|
||||
bridgeText = BuildCountReq(BRIDGE_TOKENS_HINT, BridgeTokenCount);
|
||||
}
|
||||
|
||||
return Text()+"$l"+bridgeText+"^";
|
||||
}
|
||||
|
||||
static Text BuildGanonBossKeyText() {
|
||||
Text ganonBossKeyText;
|
||||
|
||||
if (GanonsBossKey.Is(GANONSBOSSKEY_START_WITH)) {
|
||||
ganonBossKeyText = Hint(GANON_BK_START_WITH_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA)) {
|
||||
ganonBossKeyText = Hint(GANON_BK_VANILLA_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON)) {
|
||||
ganonBossKeyText = Hint(GANON_BK_OWN_DUNGEON_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_ANY_DUNGEON)) {
|
||||
ganonBossKeyText = Hint(GANON_BK_ANY_DUNGEON_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_OVERWORLD)) {
|
||||
ganonBossKeyText = Hint(GANON_BK_OVERWORLD_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_ANYWHERE)) {
|
||||
ganonBossKeyText = Hint(GANON_BK_ANYWHERE_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_VANILLA)) {
|
||||
ganonBossKeyText = Hint(LACS_VANILLA_HINT).GetText();
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_STONES)) {
|
||||
ganonBossKeyText = BuildCountReq(LACS_STONES_HINT, LACSStoneCount);
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_MEDALLIONS)) {
|
||||
ganonBossKeyText = BuildCountReq(LACS_MEDALLIONS_HINT, LACSMedallionCount);
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_REWARDS)) {
|
||||
ganonBossKeyText = BuildCountReq(LACS_REWARDS_HINT, LACSRewardCount);
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_DUNGEONS)) {
|
||||
ganonBossKeyText = BuildCountReq(LACS_DUNGEONS_HINT, LACSDungeonCount);
|
||||
|
||||
} else if (GanonsBossKey.Is(GANONSBOSSKEY_LACS_TOKENS)) {
|
||||
ganonBossKeyText = BuildCountReq(LACS_TOKENS_HINT, LACSTokenCount);
|
||||
}
|
||||
|
||||
return Text()+"$b"+ganonBossKeyText+"^";
|
||||
}
|
||||
|
||||
static void CreateAltarText() {
|
||||
|
||||
//Child Altar Text
|
||||
childAltarText = Hint(SPIRITUAL_STONE_TEXT_START).GetText()+"^"+
|
||||
//Spiritual Stones
|
||||
(StartingKokiriEmerald.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(KOKIRI_EMERALD)) +
|
||||
(StartingGoronRuby.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(GORON_RUBY)) +
|
||||
(StartingZoraSapphire.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(ZORA_SAPPHIRE)) +
|
||||
//How to open Door of Time, the event trigger is necessary to read the altar multiple times
|
||||
BuildDoorOfTimeText();
|
||||
CreateMessageFromTextObject(0x7040, 0, 2, 3, AddColorsAndFormat(childAltarText, {QM_GREEN, QM_RED, QM_BLUE}));
|
||||
|
||||
//Adult Altar Text
|
||||
adultAltarText = Hint(ADULT_ALTAR_TEXT_START).GetText()+"^"+
|
||||
//Medallion Areas
|
||||
(StartingLightMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(LIGHT_MEDALLION)) +
|
||||
(StartingForestMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(FOREST_MEDALLION)) +
|
||||
(StartingFireMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(FIRE_MEDALLION)) +
|
||||
(StartingWaterMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(WATER_MEDALLION)) +
|
||||
(StartingSpiritMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(SPIRIT_MEDALLION)) +
|
||||
(StartingShadowMedallion.Value<uint8_t>() ? Text{ "##", "##", "##" }
|
||||
: BuildDungeonRewardText(SHADOW_MEDALLION)) +
|
||||
|
||||
//Bridge requirement
|
||||
BuildBridgeReqsText()+
|
||||
|
||||
//Ganons Boss Key requirement
|
||||
BuildGanonBossKeyText()+
|
||||
|
||||
//End
|
||||
Hint(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}));
|
||||
}
|
||||
|
||||
void CreateMerchantsHints() {
|
||||
|
||||
Text medigoronItemText = Location(GC_MEDIGORON)->GetPlacedItem().GetHint().GetText();
|
||||
Text carpetSalesmanItemText = Location(WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetText();
|
||||
Text carpetSalesmanItemClearText = Location(WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetClear();
|
||||
|
||||
Text medigoronText = Hint(MEDIGORON_DIALOG_FIRST).GetText()+medigoronItemText+Hint(MEDIGORON_DIALOG_SECOND).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(0x6077, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextOne, {QM_RED, QM_GREEN}));
|
||||
CreateMessageFromTextObject(0x6078, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextTwo, {QM_RED, QM_YELLOW, QM_RED}));
|
||||
}
|
||||
|
||||
void CreateAllHints() {
|
||||
|
||||
CreateGanonText();
|
||||
CreateAltarText();
|
||||
|
||||
SPDLOG_INFO("\nNOW CREATING HINTS\n");
|
||||
const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value<uint8_t>()];
|
||||
|
||||
uint8_t remainingDungeonWothHints = hintSetting.dungeonsWothLimit;
|
||||
uint8_t remainingDungeonBarrenHints = hintSetting.dungeonsBarrenLimit;
|
||||
|
||||
// Add 'always' location hints
|
||||
if (hintSetting.distTable[static_cast<int>(HintType::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 &&
|
||||
Location(loc)->IsHintable() && !(Location(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 (uint32_t location : alwaysHintLocations) {
|
||||
CreateLocationHint({location});
|
||||
}
|
||||
}
|
||||
|
||||
//Add 'trial' location hints
|
||||
if (hintSetting.distTable[static_cast<int>(HintType::Trial)].copies > 0) {
|
||||
CreateTrialHints();
|
||||
}
|
||||
|
||||
//create a vector with each hint type proportional to it's weight in the distribution setting.
|
||||
//ootr uses a weighted probability function to decide hint types, but selecting randomly from
|
||||
//this vector will do for now
|
||||
std::vector<HintType> remainingHintTypes = {};
|
||||
for (HintDistributionSetting hds : hintSetting.distTable) {
|
||||
remainingHintTypes.insert(remainingHintTypes.end(), hds.weight, hds.type);
|
||||
}
|
||||
Shuffle(remainingHintTypes);
|
||||
|
||||
//get barren regions
|
||||
auto barrenLocations = CalculateBarrenRegions();
|
||||
|
||||
//Calculate dungeon woth/barren info
|
||||
|
||||
std::vector<std::string> dungeonNames = {"Deku Tree", "Dodongos Cavern", "Jabu Jabus Belly", "Forest Temple", "Fire Temple",
|
||||
"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;
|
||||
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()) {
|
||||
barrenDungeons.push_back(barrenRegion);
|
||||
}
|
||||
}
|
||||
SPDLOG_INFO("\nBarren Dungeons:\n");
|
||||
for (std::string barrenDungeon : barrenDungeons) {
|
||||
SPDLOG_INFO(barrenDungeon + "\n");
|
||||
}
|
||||
|
||||
//Get list of all woth dungeons
|
||||
std::vector<std::string> wothDungeons;
|
||||
for (uint32_t wothLocation : wothLocations) {
|
||||
std::string wothRegion = GetHintRegion(Location(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()) {
|
||||
wothDungeons.push_back(wothRegion);
|
||||
}
|
||||
}
|
||||
SPDLOG_INFO("\nWoth Dungeons:\n");
|
||||
for (std::string wothDungeon : wothDungeons) {
|
||||
SPDLOG_INFO(wothDungeon + "\n");
|
||||
}
|
||||
|
||||
//Set DungeonInfo array for each dungeon
|
||||
for (uint32_t i = 0; i < dungeonInfoData.size(); i++) {
|
||||
std::string dungeonName = dungeonNames[i];
|
||||
if (std::find(barrenDungeons.begin(), barrenDungeons.end(), dungeonName) != barrenDungeons.end()) {
|
||||
dungeonInfoData[i] = DungeonInfo::DUNGEON_BARREN;
|
||||
} else if (std::find(wothDungeons.begin(), wothDungeons.end(), dungeonName) != wothDungeons.end()) {
|
||||
dungeonInfoData[i] = DungeonInfo::DUNGEON_WOTH;
|
||||
} else {
|
||||
dungeonInfoData[i] = DungeonInfo::DUNGEON_NEITHER;
|
||||
}
|
||||
}
|
||||
|
||||
std::array<std::string, 13> hintTypeNames = {
|
||||
"Trial",
|
||||
"Always",
|
||||
"WotH",
|
||||
"Barren",
|
||||
"Entrance",
|
||||
"Sometimes",
|
||||
"Random",
|
||||
"Item",
|
||||
"Song",
|
||||
"Overworld",
|
||||
"Dungeon",
|
||||
"Junk",
|
||||
"NamedItem",
|
||||
};
|
||||
|
||||
//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
|
||||
|
||||
if (remainingHintTypes.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
//get a random hint type from the remaining hints
|
||||
HintType type = RandomElement(remainingHintTypes, true);
|
||||
|
||||
SPDLOG_INFO("Attempting to make hint of type: ");
|
||||
SPDLOG_INFO(hintTypeNames[static_cast<int>(type)]);
|
||||
SPDLOG_INFO("\n");
|
||||
|
||||
//create the appropriate hint for the type
|
||||
if (type == HintType::Woth) {
|
||||
CreateWothHint(&remainingDungeonWothHints);
|
||||
|
||||
} else if (type == HintType::Barren) {
|
||||
CreateBarrenHint(&remainingDungeonBarrenHints, barrenLocations);
|
||||
|
||||
} else if (type == HintType::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 == HintType::Random) {
|
||||
CreateRandomLocationHint();
|
||||
|
||||
} else if (type == HintType::Item) {
|
||||
CreateGoodItemHint();
|
||||
|
||||
} else if (type == HintType::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 == HintType::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 == HintType::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 == HintType::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});
|
||||
}
|
||||
|
||||
//Getting gossip stone locations temporarily sets one location to not be reachable.
|
||||
//Call the function one last time to get rid of false positives on locations not
|
||||
//being reachable.
|
||||
GetAccessibleLocations({});
|
||||
}
|
227
soh/soh/Enhancements/randomizer/3drando/hints.hpp
Normal file
227
soh/soh/Enhancements/randomizer/3drando/hints.hpp
Normal file
@ -0,0 +1,227 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "keys.hpp"
|
||||
#include "text.hpp"
|
||||
#include "random.hpp"
|
||||
#include "settings.hpp"
|
||||
#include <functional>
|
||||
|
||||
enum class HintType {
|
||||
Trial,
|
||||
Always,
|
||||
Woth, //Way of the Hero
|
||||
Barren,
|
||||
Entrance,
|
||||
Sometimes,
|
||||
Random,
|
||||
Item,
|
||||
Song,
|
||||
Overworld,
|
||||
Dungeon,
|
||||
Junk,
|
||||
NamedItem,
|
||||
MaxCount,
|
||||
};
|
||||
|
||||
struct HintDistributionSetting {
|
||||
HintType type;
|
||||
uint8_t order;
|
||||
size_t weight;
|
||||
uint8_t fixed;
|
||||
uint8_t copies;
|
||||
};
|
||||
|
||||
struct HintSetting {
|
||||
using DistributionTable = std::array<HintDistributionSetting, static_cast<int>(HintType::MaxCount)>;
|
||||
|
||||
uint8_t dungeonsWothLimit;
|
||||
uint8_t dungeonsBarrenLimit;
|
||||
bool namedItemsRequired;
|
||||
DistributionTable distTable;
|
||||
};
|
||||
|
||||
enum class HintCategory {
|
||||
Item,
|
||||
Always,
|
||||
Sometimes,
|
||||
Exclude,
|
||||
Entrance,
|
||||
Region,
|
||||
Junk,
|
||||
DungeonName,
|
||||
Boss,
|
||||
Bridge,
|
||||
GanonsBossKey,
|
||||
LACS,
|
||||
Altar,
|
||||
Validation,
|
||||
LightArrow,
|
||||
GanonLine,
|
||||
MerchantsDialogs,
|
||||
};
|
||||
|
||||
class HintText {
|
||||
public:
|
||||
HintText() = default;
|
||||
HintText(std::vector<Text> obscureText_, std::vector<Text> ambiguousText_, Text clearText_, HintCategory type_)
|
||||
: obscureText(std::move(obscureText_)),
|
||||
ambiguousText(std::move(ambiguousText_)),
|
||||
clearText(std::move(clearText_)),
|
||||
type(type_) {}
|
||||
|
||||
static auto Item(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Item};
|
||||
}
|
||||
|
||||
static auto Always(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Always};
|
||||
}
|
||||
|
||||
static auto Sometimes(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Sometimes};
|
||||
}
|
||||
|
||||
static auto Exclude(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Exclude};
|
||||
}
|
||||
|
||||
static auto Entrance(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Entrance};
|
||||
}
|
||||
|
||||
static auto Region(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Region};
|
||||
}
|
||||
|
||||
static auto Junk(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Junk};
|
||||
}
|
||||
|
||||
static auto DungeonName(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::DungeonName};
|
||||
}
|
||||
|
||||
static auto Boss(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Boss};
|
||||
}
|
||||
|
||||
static auto Bridge(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Bridge};
|
||||
}
|
||||
|
||||
static auto GanonsBossKey(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::GanonsBossKey};
|
||||
}
|
||||
|
||||
static auto LACS(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::LACS};
|
||||
}
|
||||
|
||||
static auto Altar(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Altar};
|
||||
}
|
||||
|
||||
static auto Validation(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Validation};
|
||||
}
|
||||
|
||||
static auto LightArrow(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::LightArrow};
|
||||
}
|
||||
|
||||
static auto GanonLine(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::GanonLine};
|
||||
}
|
||||
|
||||
static auto MerchantsDialogs(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
|
||||
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::MerchantsDialogs};
|
||||
}
|
||||
|
||||
Text& GetObscure() {
|
||||
return RandomElement(obscureText);
|
||||
}
|
||||
|
||||
const Text& GetObscure() const {
|
||||
return RandomElement(obscureText);
|
||||
}
|
||||
|
||||
Text& GetAmbiguous() {
|
||||
if (ambiguousText.size() > 0) {
|
||||
return RandomElement(ambiguousText);
|
||||
}
|
||||
return RandomElement(obscureText);
|
||||
}
|
||||
|
||||
const Text& GetAmbiguous() const {
|
||||
if (ambiguousText.size() > 0) {
|
||||
return RandomElement(ambiguousText);
|
||||
}
|
||||
return RandomElement(obscureText);
|
||||
}
|
||||
|
||||
const Text& GetClear() const {
|
||||
if (clearText.GetEnglish().empty()) {
|
||||
return GetObscure();
|
||||
}
|
||||
return clearText;
|
||||
}
|
||||
|
||||
const Text& GetText() const {
|
||||
if (Settings::ClearerHints.Is(HINTMODE_OBSCURE)) {
|
||||
return GetObscure();
|
||||
} else if (Settings::ClearerHints.Is(HINTMODE_AMBIGUOUS)){
|
||||
return GetAmbiguous();
|
||||
} else {
|
||||
return GetClear();
|
||||
}
|
||||
}
|
||||
|
||||
const Text GetTextCopy() const {
|
||||
if (Settings::ClearerHints.Is(HINTMODE_OBSCURE)) {
|
||||
return GetObscure();
|
||||
} else if (Settings::ClearerHints.Is(HINTMODE_AMBIGUOUS)){
|
||||
return GetAmbiguous();
|
||||
} else {
|
||||
return GetClear();
|
||||
}
|
||||
}
|
||||
|
||||
HintCategory GetType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
bool operator==(const HintText& right) const {
|
||||
return obscureText == right.obscureText &&
|
||||
ambiguousText == right.ambiguousText &&
|
||||
clearText == right.clearText;
|
||||
}
|
||||
bool operator!=(const HintText& right) const {
|
||||
return !operator==(right);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Text> obscureText = {};
|
||||
std::vector<Text> ambiguousText = {};
|
||||
Text clearText;
|
||||
HintCategory type;
|
||||
};
|
||||
|
||||
using ConditionalAlwaysHint = std::pair<uint32_t, 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 void CreateAllHints();
|
||||
extern void CreateMerchantsHints();
|
||||
|
||||
Text& GetChildAltarText();
|
||||
Text& GetAdultAltarText();
|
||||
Text& GetGanonText();
|
||||
Text& GetGanonHintText();
|
84
soh/soh/Enhancements/randomizer/3drando/item.cpp
Normal file
84
soh/soh/Enhancements/randomizer/3drando/item.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#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(Text name_, ItemType type_, int getItemId_, bool advancement_, bool* logicVar_, uint32_t hintKey_,
|
||||
uint16_t price_)
|
||||
: name(std::move(name_)),
|
||||
type(type_),
|
||||
getItemId(getItemId_),
|
||||
advancement(advancement_),
|
||||
logicVar(logicVar_),
|
||||
hintKey(hintKey_),
|
||||
price(price_) {}
|
||||
|
||||
Item::Item(Text name_, ItemType type_, int getItemId_, bool advancement_, uint8_t* logicVar_, uint32_t hintKey_,
|
||||
uint16_t price_)
|
||||
: 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 (!Settings::ColoredBossKeys && (getItemId >= 0x95 && getItemId <= 0x9A)) { //Boss keys
|
||||
val.looksLikeItemId = GI_KEY_BOSS;
|
||||
}
|
||||
if (!Settings::ColoredKeys && (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;
|
||||
}
|
142
soh/soh/Enhancements/randomizer/3drando/item.hpp
Normal file
142
soh/soh/Enhancements/randomizer/3drando/item.hpp
Normal file
@ -0,0 +1,142 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include "keys.hpp"
|
||||
#include "hint_list.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
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(Text name_, ItemType type_, int getItemId_, bool advancement_, bool* logicVar_, uint32_t hintKey_,
|
||||
uint16_t price_ = 0);
|
||||
Item(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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// PURPLE TODO: LOCALIZATION
|
||||
if (name.GetEnglish().find("Bombchus") != std::string::npos && !BombchusInLogic) {
|
||||
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 != 0x9A) && (BossKeysanity.Is(BOSSKEYSANITY_VANILLA) || BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON))) {
|
||||
return false;
|
||||
}
|
||||
//Ganons Castle Boss Key
|
||||
if (getItemId == 0x9A && (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA) || GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsAdvancement();
|
||||
}
|
||||
|
||||
const 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:
|
||||
Text name;
|
||||
ItemType type;
|
||||
int getItemId;
|
||||
bool advancement;
|
||||
std::variant<bool*, uint8_t*> logicVar;
|
||||
uint32_t hintKey;
|
||||
uint16_t price;
|
||||
bool playthrough = false;
|
||||
};
|
290
soh/soh/Enhancements/randomizer/3drando/item_list.cpp
Normal file
290
soh/soh/Enhancements/randomizer/3drando/item_list.cpp
Normal file
@ -0,0 +1,290 @@
|
||||
#include "item_list.hpp"
|
||||
|
||||
#include "logic.hpp"
|
||||
#include <array>
|
||||
#include "z64item.h"
|
||||
|
||||
using namespace Logic;
|
||||
|
||||
static std::array<Item, KEY_ENUM_MAX> itemTable;
|
||||
|
||||
void ItemTable_Init() { //English name French Spanish Item Type getItemID advancement logic hint key
|
||||
itemTable[NONE] = Item(Text{"No Item", "Rien", "Sin Objeto"}, ITEMTYPE_EVENT, GI_RUPEE_GREEN, false, &noVariable, NONE);
|
||||
itemTable[KOKIRI_SWORD] = Item(Text{"Kokiri Sword", "Épée Kokiri", "Espada Kokiri"}, ITEMTYPE_ITEM, GI_SWORD_KOKIRI, true, &KokiriSword, KOKIRI_SWORD);
|
||||
//[MASTER_SWORD]
|
||||
itemTable[GIANTS_KNIFE] = Item(Text{"Giant's Knife", "Lame des Géants", "Espada de Biggoron"}, ITEMTYPE_ITEM, GI_SWORD_KNIFE, false, &noVariable, GIANTS_KNIFE);
|
||||
itemTable[BIGGORON_SWORD] = Item(Text{"Biggoron's Sword", "Épée de Biggoron", "Espada de Biggoron"}, ITEMTYPE_ITEM, GI_SWORD_BGS, true, &BiggoronSword, BIGGORON_SWORD);
|
||||
itemTable[DEKU_SHIELD] = Item(Text{"Deku Shield", "Bouclier Mojo", "Escudo deku"}, ITEMTYPE_ITEM, GI_SHIELD_DEKU, false, &noVariable, DEKU_SHIELD);
|
||||
itemTable[HYLIAN_SHIELD] = Item(Text{"Hylian Shield", "Bouclier Hylien", "Escudo hyliano"}, ITEMTYPE_ITEM, GI_SHIELD_HYLIAN, false, &noVariable, HYLIAN_SHIELD);
|
||||
itemTable[MIRROR_SHIELD] = Item(Text{"Mirror Shield", "Bouclier Miroir", "Escudo espejo"}, ITEMTYPE_ITEM, GI_SHIELD_MIRROR, true, &MirrorShield, MIRROR_SHIELD);
|
||||
itemTable[GORON_TUNIC] = Item(Text{"Goron Tunic", "Tunique Goron", "Sayo goron"}, ITEMTYPE_ITEM, GI_TUNIC_GORON, true, &GoronTunic, GORON_TUNIC);
|
||||
itemTable[ZORA_TUNIC] = Item(Text{"Zora Tunic", "Tunique Zora", "Sayo zora"}, ITEMTYPE_ITEM, GI_TUNIC_ZORA, true, &ZoraTunic, ZORA_TUNIC);
|
||||
itemTable[IRON_BOOTS] = Item(Text{"Iron Boots", "Bottes de plomb", "Botas de hierro"}, ITEMTYPE_ITEM, GI_BOOTS_IRON, true, &IronBoots, IRON_BOOTS);
|
||||
itemTable[HOVER_BOOTS] = Item(Text{"Hover Boots", "Bottes des airs", "Botas voladoras"}, ITEMTYPE_ITEM, GI_BOOTS_HOVER, true, &HoverBoots, HOVER_BOOTS);
|
||||
|
||||
|
||||
itemTable[BOOMERANG] = Item(Text{"Boomerang", "Boomerang", "Búmeran"}, ITEMTYPE_ITEM, GI_BOOMERANG, true, &Boomerang, BOOMERANG);
|
||||
itemTable[LENS_OF_TRUTH] = Item(Text{"Lens of Truth", "Monocle de Vérité", "Lupa de la Verdad"}, ITEMTYPE_ITEM, GI_LENS, true, &LensOfTruth, LENS_OF_TRUTH);
|
||||
itemTable[MEGATON_HAMMER] = Item(Text{"Megaton Hammer", "Masse des Titans", "Martillo Megatón"}, ITEMTYPE_ITEM, GI_HAMMER, true, &Hammer, MEGATON_HAMMER);
|
||||
itemTable[STONE_OF_AGONY] = Item(Text{"Stone of Agony", "Pierre de Souffrance", "Piedra de la Agonía"}, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, &ShardOfAgony, STONE_OF_AGONY);
|
||||
itemTable[DINS_FIRE] = Item(Text{"Din's Fire", "Feu de Din", "Fuego de Din"}, ITEMTYPE_ITEM, GI_DINS_FIRE, true, &DinsFire, DINS_FIRE);
|
||||
itemTable[FARORES_WIND] = Item(Text{"Farore's Wind", "Vent de Farore", "Viento de Farore"}, ITEMTYPE_ITEM, GI_FARORES_WIND, true, &FaroresWind, FARORES_WIND);
|
||||
itemTable[NAYRUS_LOVE] = Item(Text{"Nayru's Love", "Amour de Nayru", "Amor de Nayru"}, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, &NayrusLove, NAYRUS_LOVE);
|
||||
itemTable[FIRE_ARROWS] = Item(Text{"Fire Arrow", "Flèche de Feu", "Flecha de fuego"}, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, &FireArrows, FIRE_ARROWS);
|
||||
itemTable[ICE_ARROWS] = Item(Text{"Ice Arrow", "Flèche de Glace", "Flecha de hielo"}, ITEMTYPE_ITEM, GI_ARROW_ICE, true, &IceArrows, ICE_ARROWS);
|
||||
itemTable[LIGHT_ARROWS] = Item(Text{"Light Arrow", "Flèche de Lumière", "Flecha de luz"}, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, &LightArrows, LIGHT_ARROWS);
|
||||
itemTable[GERUDO_MEMBERSHIP_CARD] = Item(Text{"Gerudo Membership Card", "Carte Gerudo", "Pase de socio gerudo"}, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, &GerudoToken, GERUDO_MEMBERSHIP_CARD);
|
||||
itemTable[MAGIC_BEAN] = Item(Text{"Magic Bean", "Haricots Magiques", "Habichuelas mágicas"}, ITEMTYPE_ITEM, GI_BEAN, true, &MagicBean, MAGIC_BEAN);
|
||||
itemTable[MAGIC_BEAN_PACK] = Item(Text{"Magic Bean Pack", "Paquet de Haricots Magiques", "Lote de habichuelas mágicas"}, ITEMTYPE_ITEM, 0xC9, true, &MagicBeanPack, MAGIC_BEAN_PACK);
|
||||
itemTable[DOUBLE_DEFENSE] = Item(Text{"Double Defense", "Double Défence", "Doble poder defensivo"}, ITEMTYPE_ITEM, 0xB8, true, &DoubleDefense, DOUBLE_DEFENSE);
|
||||
|
||||
itemTable[WEIRD_EGG] = Item(Text{"Weird Egg", "Oeuf Curieux", "Huevo extraño"}, ITEMTYPE_ITEM, GI_WEIRD_EGG, true, &WeirdEgg, WEIRD_EGG);
|
||||
// itemTable[CUCCO] = Item(Text{"Cucco", "Cocotte", "Cuco"}, ITEMTYPE_ITEM, GI_CUCCO, true, &Cucco, CUCCO);
|
||||
itemTable[ZELDAS_LETTER] = Item(Text{"Zelda's Letter", "Lettre de Zelda", "Carta de Zelda"}, ITEMTYPE_ITEM, GI_LETTER_ZELDA, true, &ZeldasLetter, ZELDAS_LETTER);
|
||||
// itemTable[KEATON_MASK] = Item(Text{"Keaton Mask", "Masque du Renard", "Careta de Keaton"}, ITEMTYPE_ITEM, GI_MASK_KEATON, true, &KeatonMask, KEATON_MASK);
|
||||
// itemTable[SKULL_MASK] = Item(Text{"Skull Mask", "Masque de Mort", "Máscara de calavera"}, ITEMTYPE_ITEM, GI_MASK_SKULL, true, &SkullMask, SKULL_MASK);
|
||||
// itemTable[SPOOKY_MASK] = Item(Text{"Spooky Mask", "Masque d'Effroi", "Máscara tenebrosa"}, ITEMTYPE_ITEM, GI_MASK_SPOOKY, true, &SpookyMask, SPOOKY_MASK);
|
||||
// itemTable[BUNNY_HOOD] = Item(Text{"Bunny Hood", "Masque du Lapin", "Capucha de conejo"}, ITEMTYPE_ITEM, GI_MASK_BUNNY, true, &BunnyHood, BUNNY_HOOD);
|
||||
// itemTable[GORON_MASK] = Item(Text{"Goron Mask", "Masque de Goron", "Máscara Goron"}, ITEMTYPE_ITEM, GI_MASK_GORON, true, &GoronMask, GORON_MASK);
|
||||
// itemTable[ZORA_MASK] = Item(Text{"Zora Mask", "Masque de Zora", "Máscara Zora"}, ITEMTYPE_ITEM, GI_MASK_ZORA, true, &ZoraMask, ZORA_MASK);
|
||||
// itemTable[GERUDO_MASK] = Item(Text{"Gerudo Mask", "Masque de Gerudo", "Máscara Gerudo"}, ITEMTYPE_ITEM, GI_MASK_GERUDO, true, &GerudoMask, GERUDO_MASK);
|
||||
// itemTable[MASK_OF_TRUTH] = Item(Text{"Mask of Truth", "Masque de Vérité", "Máscara de la Verdad"}, ITEMTYPE_ITEM, GI_MASK_MASK, true, &MaskofTruth, MASK_OF_TRUTH);
|
||||
itemTable[POCKET_EGG] = Item(Text{"Pocket Egg", "Oeuf de poche", "Huevo de bolsillo"}, ITEMTYPE_ITEM, GI_POCKET_EGG, true, &PocketEgg, POCKET_EGG);
|
||||
// itemTable[POCKET_CUCCO] = Item(Text{"Pocket Cucco", "Cocotte de poche", "Cuco de bolsillo"}, ITEMTYPE_ITEM, GI_POCKET_CUCCO, true, &PocketCucco, POCKET_CUCCO);
|
||||
itemTable[COJIRO] = Item(Text{"Cojiro", "P'tit Poulet", "Cojiro"}, ITEMTYPE_ITEM, GI_COJIRO, true, &Cojiro, COJIRO);
|
||||
itemTable[ODD_MUSHROOM] = Item(Text{"Odd Mushroom", "Champignon Suspect", "Champiñón extraño"}, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, &OddMushroom, ODD_MUSHROOM);
|
||||
itemTable[ODD_POTION] = Item(Text{"Odd Potion", "Mixture Suspecte", "Medicina rara"}, ITEMTYPE_ITEM, GI_ODD_POTION, true, &OddPoultice, ODD_POTION);
|
||||
itemTable[POACHERS_SAW] = Item(Text{"Poacher's Saw", "Scie du Chasseur", "Sierra del furtivo"}, ITEMTYPE_ITEM, GI_SAW, true, &PoachersSaw, POACHERS_SAW);
|
||||
itemTable[BROKEN_SWORD] = Item(Text{"Broken Goron's Sword", "Épée Brisée de Goron", "Espada goron rota"}, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, &BrokenSword, BROKEN_SWORD);
|
||||
itemTable[PRESCRIPTION] = Item(Text{"Prescription", "Ordonnance", "Receta"}, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, &Prescription, PRESCRIPTION);
|
||||
itemTable[EYEBALL_FROG] = Item(Text{"Eyeball Frog", "Crapaud-qui-louche", "Rana de ojos saltones"}, ITEMTYPE_ITEM, GI_FROG, true, &EyeballFrog, EYEBALL_FROG);
|
||||
itemTable[EYEDROPS] = Item(Text{"World's Finest Eyedrops", "Super Gouttes", "Supergotas oculares"}, ITEMTYPE_ITEM, GI_EYEDROPS, true, &Eyedrops, EYEDROPS);
|
||||
itemTable[CLAIM_CHECK] = Item(Text{"Claim Check", "Certificat", "Recibo"}, ITEMTYPE_ITEM, GI_CLAIM_CHECK, true, &ClaimCheck, CLAIM_CHECK);
|
||||
|
||||
itemTable[GOLD_SKULLTULA_TOKEN] = Item(Text{"Gold Skulltula Token", "Symbole de Skulltula d'Or", "Símbolo de skulltula dorada"}, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, &GoldSkulltulaTokens, GOLD_SKULLTULA_TOKEN);
|
||||
|
||||
//Progression Items
|
||||
itemTable[PROGRESSIVE_HOOKSHOT] = Item(Text{"Progressive Hookshot", "Grappin (prog.)", "Gancho progresivo"}, ITEMTYPE_ITEM, 0x80, true, &ProgressiveHookshot, PROGRESSIVE_HOOKSHOT);
|
||||
itemTable[PROGRESSIVE_STRENGTH] = Item(Text{"Progressive Strength Upgrade", "Amélioration de Force (prog.)", "Fuerza progresiva"}, ITEMTYPE_ITEM, 0x81, true, &ProgressiveStrength, PROGRESSIVE_STRENGTH);
|
||||
itemTable[PROGRESSIVE_BOMB_BAG] = Item(Text{"Progressive Bomb Bag", "Sac de Bombes (prog.)", "Saco de bombas progresivo"}, ITEMTYPE_ITEM, 0x82, true, &ProgressiveBombBag, PROGRESSIVE_BOMB_BAG);
|
||||
itemTable[PROGRESSIVE_BOW] = Item(Text{"Progressive Bow", "Arc (prog.)", "Arco progresivo"}, ITEMTYPE_ITEM, 0x83, true, &ProgressiveBow, PROGRESSIVE_BOW);
|
||||
itemTable[PROGRESSIVE_SLINGSHOT] = Item(Text{"Progressive Slingshot", "Lance-Pierre (prog.)", "Resortera progresiva"}, ITEMTYPE_ITEM, 0x84, true, &ProgressiveBulletBag, PROGRESSIVE_SLINGSHOT);
|
||||
itemTable[PROGRESSIVE_WALLET] = Item(Text{"Progressive Wallet", "Bourse (prog.)", "Bolsa de rupias progresiva"}, ITEMTYPE_ITEM, 0x85, true, &ProgressiveWallet, PROGRESSIVE_WALLET);
|
||||
itemTable[PROGRESSIVE_SCALE] = Item(Text{"Progressive Scale", "Écaille (prog.)", "Escama progresiva"}, ITEMTYPE_ITEM, 0x86, true, &ProgressiveScale, PROGRESSIVE_SCALE);
|
||||
itemTable[PROGRESSIVE_NUT_UPGRADE] = Item(Text{"Progressive Nut Capacity", "Capacité de Noix (prog.)", "Capacidad de nueces deku progresiva"}, ITEMTYPE_ITEM, 0x87, false, &noVariable, PROGRESSIVE_NUT_UPGRADE);
|
||||
itemTable[PROGRESSIVE_STICK_UPGRADE] = Item(Text{"Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Capacidad de palos deku progresiva"}, ITEMTYPE_ITEM, 0x88, false, &noVariable, PROGRESSIVE_STICK_UPGRADE);
|
||||
itemTable[PROGRESSIVE_BOMBCHUS] = Item(Text{"Progressive Bombchu", "Missiles (prog.)", "Bombchus progresivos"}, ITEMTYPE_ITEM, 0x89, true, &Bombchus, PROGRESSIVE_BOMBCHUS);
|
||||
itemTable[PROGRESSIVE_MAGIC_METER] = Item(Text{"Progressive Magic Meter", "Jauge de Magie (prog.)", "Poder mágico progresivo"}, ITEMTYPE_ITEM, 0x8A, true, &ProgressiveMagic, PROGRESSIVE_MAGIC_METER);
|
||||
itemTable[PROGRESSIVE_OCARINA] = Item(Text{"Progressive Ocarina", "Ocarina (prog.)", "Ocarina progresiva"}, ITEMTYPE_ITEM, 0x8B, true, &ProgressiveOcarina, PROGRESSIVE_OCARINA);
|
||||
itemTable[PROGRESSIVE_GORONSWORD] = Item(Text{"Progressive Goron Sword", "Épée Goron (prog.)", "Espada Goron progresiva"}, ITEMTYPE_ITEM, 0xD4, true, &ProgressiveGiantKnife, PROGRESSIVE_GORONSWORD);
|
||||
|
||||
//Bottles
|
||||
itemTable[EMPTY_BOTTLE] = Item(Text{"Empty Bottle", "Bouteille Vide", "Botella vacía"}, ITEMTYPE_ITEM, 0x0F, true, &Bottles, EMPTY_BOTTLE);
|
||||
itemTable[BOTTLE_WITH_MILK] = Item(Text{"Bottle with Milk", "Bouteille avec du Lait", "Botella de leche Lon Lon"}, ITEMTYPE_ITEM, 0x14, true, &Bottles, BOTTLE_WITH_MILK);
|
||||
itemTable[BOTTLE_WITH_RED_POTION] = Item(Text{"Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Botella de poción roja"}, ITEMTYPE_ITEM, 0x8C, true, &Bottles, BOTTLE_WITH_RED_POTION);
|
||||
itemTable[BOTTLE_WITH_GREEN_POTION] = Item(Text{"Bottle with Green Potion", "Bouteille avec une Potion Verte", "Botella de poción verde"}, ITEMTYPE_ITEM, 0x8D, true, &Bottles, BOTTLE_WITH_GREEN_POTION);
|
||||
itemTable[BOTTLE_WITH_BLUE_POTION] = Item(Text{"Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Botella de poción azul"}, ITEMTYPE_ITEM, 0x8E, true, &Bottles, BOTTLE_WITH_BLUE_POTION);
|
||||
itemTable[BOTTLE_WITH_FAIRY] = Item(Text{"Bottle with Fairy", "Bouteille avec une Fée", "Hada en una botella"}, ITEMTYPE_ITEM, 0x8F, true, &Bottles, BOTTLE_WITH_FAIRY);
|
||||
itemTable[BOTTLE_WITH_FISH] = Item(Text{"Bottle with Fish", "Bouteille avec un Poisson", "Pez en una botella"}, ITEMTYPE_ITEM, 0x90, true, &Bottles, BOTTLE_WITH_FISH);
|
||||
itemTable[BOTTLE_WITH_BLUE_FIRE] = Item(Text{"Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Botella de fuego azul"}, ITEMTYPE_ITEM, 0x91, true, &Bottles, BOTTLE_WITH_BLUE_FIRE);
|
||||
itemTable[BOTTLE_WITH_BUGS] = Item(Text{"Bottle with Bugs", "Bouteille avec des Insectes", "Insecto en una botella"}, ITEMTYPE_ITEM, 0x92, true, &Bottles, BOTTLE_WITH_BUGS);
|
||||
itemTable[BOTTLE_WITH_POE] = Item(Text{"Bottle with Poe", "Bouteille avec un Esprit", "Poe en una botella"}, ITEMTYPE_ITEM, 0x94, true, &Bottles, BOTTLE_WITH_POE);
|
||||
|
||||
//Special bottles that can't immediately dump contents
|
||||
itemTable[RUTOS_LETTER] = Item(Text{"Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Carta de Ruto"}, ITEMTYPE_ITEM, 0x15, true, &RutosLetter, RUTOS_LETTER);
|
||||
itemTable[BOTTLE_WITH_BIG_POE] = Item(Text{"Bottle with Big Poe", "Bouteille avec une Âme", "Gran Poe en una botella"}, ITEMTYPE_ITEM, 0x93, true, &BottleWithBigPoe, BOTTLE_WITH_BIG_POE);
|
||||
|
||||
//Songs
|
||||
itemTable[ZELDAS_LULLABY] = Item(Text{"Zelda's Lullaby", "Berceuse de Zelda", "Nana de Zelda"}, ITEMTYPE_SONG, 0xC1, true, &ZeldasLullaby, ZELDAS_LULLABY);
|
||||
itemTable[EPONAS_SONG] = Item(Text{"Epona's Song", "Chant d'Épona", "Canción de Epona"}, ITEMTYPE_SONG, 0xC2, true, &EponasSong, EPONAS_SONG);
|
||||
itemTable[SARIAS_SONG] = Item(Text{"Saria's Song", "Chant de Saria", "Canción de Saria"}, ITEMTYPE_SONG, 0xC3, true, &SariasSong, SARIAS_SONG);
|
||||
itemTable[SUNS_SONG] = Item(Text{"Sun's Song", "Chant du Soleil", "Canción del Sol"}, ITEMTYPE_SONG, 0xC4, true, &SunsSong, SUNS_SONG);
|
||||
itemTable[SONG_OF_TIME] = Item(Text{"Song of Time", "Chant du Temps", "Canción del tiempo"}, ITEMTYPE_SONG, 0xC5, true, &SongOfTime, SONG_OF_TIME);
|
||||
itemTable[SONG_OF_STORMS] = Item(Text{"Song of Storms", "Chant des Tempêtes", "Canción de la tormenta"}, ITEMTYPE_SONG, 0xC6, true, &SongOfStorms, SONG_OF_STORMS);
|
||||
itemTable[MINUET_OF_FOREST] = Item(Text{"Minuet of Forest", "Menuet des Bois", "Minueto del bosque"}, ITEMTYPE_SONG, 0xBB, true, &MinuetOfForest, MINUET_OF_FOREST);
|
||||
itemTable[BOLERO_OF_FIRE] = Item(Text{"Bolero of Fire", "Boléro du Feu", "Bolero del fuego"}, ITEMTYPE_SONG, 0xBC, true, &BoleroOfFire, BOLERO_OF_FIRE);
|
||||
itemTable[SERENADE_OF_WATER] = Item(Text{"Serenade of Water", "Sérénade de l'Eau", "Serenata del agua"}, ITEMTYPE_SONG, 0xBD, true, &SerenadeOfWater, SERENADE_OF_WATER);
|
||||
itemTable[REQUIEM_OF_SPIRIT] = Item(Text{"Requiem of Spirit", "Requiem des Esprits", "Réquiem del espíritu"}, ITEMTYPE_SONG, 0xBE, true, &RequiemOfSpirit, REQUIEM_OF_SPIRIT);
|
||||
itemTable[NOCTURNE_OF_SHADOW] = Item(Text{"Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturno de la sombra"}, ITEMTYPE_SONG, 0xBF, true, &NocturneOfShadow, NOCTURNE_OF_SHADOW);
|
||||
itemTable[PRELUDE_OF_LIGHT] = Item(Text{"Prelude of Light", "Prélude de la Lumière", "Preludio de la luz"}, ITEMTYPE_SONG, 0xC0, true, &PreludeOfLight, PRELUDE_OF_LIGHT);
|
||||
|
||||
//Maps and Compasses
|
||||
itemTable[DEKU_TREE_MAP] = Item(Text{"Great Deku Tree Map", "Carte de l'Arbre Mojo", "Mapa del Gran Árbol Deku"}, ITEMTYPE_MAP, 0xA5, false, &noVariable, DEKU_TREE_MAP);
|
||||
itemTable[DODONGOS_CAVERN_MAP] = Item(Text{"Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Mapa de la Cueva de los Dodongos"}, ITEMTYPE_MAP, 0xA6, false, &noVariable, DODONGOS_CAVERN_MAP);
|
||||
itemTable[JABU_JABUS_BELLY_MAP] = Item(Text{"Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Mapa de la tripa de Jabu-Jabu"}, ITEMTYPE_MAP, 0xA7, false, &noVariable, JABU_JABUS_BELLY_MAP);
|
||||
itemTable[FOREST_TEMPLE_MAP] = Item(Text{"Forest Temple Map", "Carte du Temple de la Forêt", "Mapa del Templo del Bosque"}, ITEMTYPE_MAP, 0xA8, false, &noVariable, FOREST_TEMPLE_MAP);
|
||||
itemTable[FIRE_TEMPLE_MAP] = Item(Text{"Fire Temple Map", "Carte du Temple du Feu", "Mapa del Templo del Fuego"}, ITEMTYPE_MAP, 0xA9, false, &noVariable, FIRE_TEMPLE_MAP);
|
||||
itemTable[WATER_TEMPLE_MAP] = Item(Text{"Water Temple Map", "Carte du Temple de l'Eau", "Mapa del Templo del Agua"}, ITEMTYPE_MAP, 0xAA, false, &noVariable, WATER_TEMPLE_MAP);
|
||||
itemTable[SPIRIT_TEMPLE_MAP] = Item(Text{"Spirit Temple Map", "Carte du Temple de l'Esprit", "Mapa del Templo del Espíritu"}, ITEMTYPE_MAP, 0xAB, false, &noVariable, SPIRIT_TEMPLE_MAP);
|
||||
itemTable[SHADOW_TEMPLE_MAP] = Item(Text{"Shadow Temple Map", "Carte du Temple de l'Ombre", "Mapa del Templo de la Sombra"}, ITEMTYPE_MAP, 0xAC, false, &noVariable, SHADOW_TEMPLE_MAP);
|
||||
itemTable[BOTTOM_OF_THE_WELL_MAP] = Item(Text{"Bottom of the Well Map", "Carte du Puits", "Mapa del fondo del pozo"}, ITEMTYPE_MAP, 0xAD, false, &noVariable, BOTTOM_OF_THE_WELL_MAP);
|
||||
itemTable[ICE_CAVERN_MAP] = Item(Text{"Ice Cavern Map", "Carte de la Caverne Polaire", "Mapa de la caverna de hielo"}, ITEMTYPE_MAP, 0xAE, false, &noVariable, ICE_CAVERN_MAP);
|
||||
|
||||
itemTable[DEKU_TREE_COMPASS] = Item(Text{"Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Brújula del Gran Árbol Deku"}, ITEMTYPE_COMPASS, 0x9B, false, &noVariable, DEKU_TREE_COMPASS);
|
||||
itemTable[DODONGOS_CAVERN_COMPASS] = Item(Text{"Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Brújula de la Cueva de los Dodongos"}, ITEMTYPE_COMPASS, 0x9C, false, &noVariable, DODONGOS_CAVERN_COMPASS);
|
||||
itemTable[JABU_JABUS_BELLY_COMPASS] = Item(Text{"Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Brújula de la tripa de Jabu-Jabu"}, ITEMTYPE_COMPASS, 0x9D, false, &noVariable, JABU_JABUS_BELLY_COMPASS);
|
||||
itemTable[FOREST_TEMPLE_COMPASS] = Item(Text{"Forest Temple Compass", "Boussole du Temple de la Forêt", "Brújula del Templo del Bosque"}, ITEMTYPE_COMPASS, 0x9E, false, &noVariable, FOREST_TEMPLE_COMPASS);
|
||||
itemTable[FIRE_TEMPLE_COMPASS] = Item(Text{"Fire Temple Compass", "Boussole du Temple du Feu", "Brújula del Templo del Fuego"}, ITEMTYPE_COMPASS, 0x9F, false, &noVariable, FIRE_TEMPLE_COMPASS);
|
||||
itemTable[WATER_TEMPLE_COMPASS] = Item(Text{"Water Temple Compass", "Boussole du Temple de l'Eau", "Brújula del Templo del Agua"}, ITEMTYPE_COMPASS, 0xA0, false, &noVariable, WATER_TEMPLE_COMPASS);
|
||||
itemTable[SPIRIT_TEMPLE_COMPASS] = Item(Text{"Spirit Temple Compass", "Boussole du Temple de l'Esprit", "Brújula del Templo del Espíritu"}, ITEMTYPE_COMPASS, 0xA1, false, &noVariable, SPIRIT_TEMPLE_COMPASS);
|
||||
itemTable[SHADOW_TEMPLE_COMPASS] = Item(Text{"Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Brújula del Templo de las Sombras"}, ITEMTYPE_COMPASS, 0xA2, false, &noVariable, SHADOW_TEMPLE_COMPASS);
|
||||
itemTable[BOTTOM_OF_THE_WELL_COMPASS] = Item(Text{"Bottom of the Well Compass", "Boussole du Puits", "Brújula del fondo del pozo"}, ITEMTYPE_COMPASS, 0xA3, false, &noVariable, BOTTOM_OF_THE_WELL_COMPASS);
|
||||
itemTable[ICE_CAVERN_COMPASS] = Item(Text{"Ice Cavern Compass", "Boussole de la Caverne Polaire", "Brújula de la caverna de hielo"}, ITEMTYPE_COMPASS, 0xA4, false, &noVariable, ICE_CAVERN_COMPASS);
|
||||
|
||||
//Boss Keys
|
||||
itemTable[FOREST_TEMPLE_BOSS_KEY] = Item(Text{"Forest Temple Big Key", "Clé d'Or du Temple de la Forêt", "Gran llave del Templo del Bosque"}, ITEMTYPE_BOSSKEY, 0x95, true, &BossKeyForestTemple, FOREST_TEMPLE_BOSS_KEY);
|
||||
itemTable[FIRE_TEMPLE_BOSS_KEY] = Item(Text{"Fire Temple Big Key", "Clé d'Or du Temple du Feu", "Gran llave del Templo del Fuego"}, ITEMTYPE_BOSSKEY, 0x96, true, &BossKeyFireTemple, FIRE_TEMPLE_BOSS_KEY);
|
||||
itemTable[WATER_TEMPLE_BOSS_KEY] = Item(Text{"Water Temple Big Key", "Clé d'Or du Temple de l'Eau", "Gran llave del Templo del Agua"}, ITEMTYPE_BOSSKEY, 0x97, true, &BossKeyWaterTemple, WATER_TEMPLE_BOSS_KEY);
|
||||
itemTable[SPIRIT_TEMPLE_BOSS_KEY] = Item(Text{"Spirit Temple Big Key", "Clé d'Or du Temple de l'Esprit", "Gran llave del Templo del Espíritu"}, ITEMTYPE_BOSSKEY, 0x98, true, &BossKeySpiritTemple, SPIRIT_TEMPLE_BOSS_KEY);
|
||||
itemTable[SHADOW_TEMPLE_BOSS_KEY] = Item(Text{"Shadow Temple Big Key", "Clé d'Or du Temple de l'Ombre", "Gran llave del Templo de las Sombras"}, ITEMTYPE_BOSSKEY, 0x99, true, &BossKeyShadowTemple, SHADOW_TEMPLE_BOSS_KEY);
|
||||
itemTable[GANONS_CASTLE_BOSS_KEY] = Item(Text{"Ganon's Castle Big Key", "Clé d'Or du Château de Ganon", "Gran llave del Castillo de Ganon"}, ITEMTYPE_BOSSKEY, 0x9A, true, &BossKeyGanonsCastle, GANONS_CASTLE_BOSS_KEY);
|
||||
|
||||
//Small Keys
|
||||
itemTable[FOREST_TEMPLE_SMALL_KEY] = Item(Text{"Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Llave del Templo del Bosque"}, ITEMTYPE_SMALLKEY, 0xAF, true, &ForestTempleKeys, FOREST_TEMPLE_SMALL_KEY);
|
||||
itemTable[FIRE_TEMPLE_SMALL_KEY] = Item(Text{"Fire Temple Small Key", "Petite Clé du Temple du Feu", "Llave del Templo del Fuego"}, ITEMTYPE_SMALLKEY, 0xB0, true, &FireTempleKeys, FIRE_TEMPLE_SMALL_KEY);
|
||||
itemTable[WATER_TEMPLE_SMALL_KEY] = Item(Text{"Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Llave del Templo del Agua"}, ITEMTYPE_SMALLKEY, 0xB1, true, &WaterTempleKeys, WATER_TEMPLE_SMALL_KEY);
|
||||
itemTable[SPIRIT_TEMPLE_SMALL_KEY] = Item(Text{"Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Llave del Templo del Espíritu"}, ITEMTYPE_SMALLKEY, 0xB2, true, &SpiritTempleKeys, SPIRIT_TEMPLE_SMALL_KEY);
|
||||
itemTable[SHADOW_TEMPLE_SMALL_KEY] = Item(Text{"Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Llave del Templo de las Sombras"}, ITEMTYPE_SMALLKEY, 0xB3, true, &ShadowTempleKeys, SHADOW_TEMPLE_SMALL_KEY);
|
||||
itemTable[BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(Text{"Bottom of the Well Small Key", "Petite Clé du Puits", "Llave del fondo del pozo"}, ITEMTYPE_SMALLKEY, 0xB4, true, &BottomOfTheWellKeys, BOTTOM_OF_THE_WELL_SMALL_KEY);
|
||||
itemTable[GERUDO_TRAINING_GROUNDS_SMALL_KEY] = Item(Text{"Training Grounds Small Key", "Petite Clé du Gymnase Gerudo", "Llave del Centro de Instrucción"}, ITEMTYPE_SMALLKEY, 0xB5, true, &GerudoTrainingGroundsKeys, GERUDO_TRAINING_GROUNDS_SMALL_KEY);
|
||||
itemTable[GERUDO_FORTRESS_SMALL_KEY] = Item(Text{"Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs","Llave de la Fortaleza Gerudo"}, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, &GerudoFortressKeys, GERUDO_FORTRESS_SMALL_KEY);
|
||||
itemTable[GANONS_CASTLE_SMALL_KEY] = Item(Text{"Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Llave del Castillo de Ganon"}, ITEMTYPE_SMALLKEY, 0xB7, true, &GanonsCastleKeys, GANONS_CASTLE_SMALL_KEY);
|
||||
itemTable[TREASURE_GAME_SMALL_KEY] = Item(Text{"Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Llave del Cofre del Tesoro"}, ITEMTYPE_ITEM, 0xDE, true, &TreasureGameKeys, TREASURE_GAME_SMALL_KEY);
|
||||
|
||||
// Key Rings
|
||||
itemTable[FOREST_TEMPLE_KEY_RING] = Item(Text{"Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Llavero del Templo del Bosque"}, ITEMTYPE_SMALLKEY, 0xD5, true, &ForestTempleKeys, FOREST_TEMPLE_KEY_RING);
|
||||
itemTable[FIRE_TEMPLE_KEY_RING] = Item(Text{"Fire Temple Key Ring", "Trousseau du Temple du Feu", "Llavero del Templo del Fuego"}, ITEMTYPE_SMALLKEY, 0xD6, true, &FireTempleKeys, FIRE_TEMPLE_KEY_RING);
|
||||
itemTable[WATER_TEMPLE_KEY_RING] = Item(Text{"Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Llavero del Templo del Agua"}, ITEMTYPE_SMALLKEY, 0xD7, true, &WaterTempleKeys, WATER_TEMPLE_KEY_RING);
|
||||
itemTable[SPIRIT_TEMPLE_KEY_RING] = Item(Text{"Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Llavero del Templo del Espíritu"}, ITEMTYPE_SMALLKEY, 0xD8, true, &SpiritTempleKeys, SPIRIT_TEMPLE_KEY_RING);
|
||||
itemTable[SHADOW_TEMPLE_KEY_RING] = Item(Text{"Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Llavero del Templo de las Sombras"}, ITEMTYPE_SMALLKEY, 0xD9, true, &ShadowTempleKeys, SHADOW_TEMPLE_KEY_RING);
|
||||
itemTable[BOTTOM_OF_THE_WELL_KEY_RING] = Item(Text{"Bottom of the Well Key Ring", "Trousseau du Puits", "Llavero del fondo del pozo"}, ITEMTYPE_SMALLKEY, 0xDA, true, &BottomOfTheWellKeys, BOTTOM_OF_THE_WELL_KEY_RING);
|
||||
itemTable[GERUDO_TRAINING_GROUNDS_KEY_RING] = Item(Text{"Training Grounds Key Ring", "Trousseau du Gymnase Gerudo", "Llavero del Centro de Instrucción"}, ITEMTYPE_SMALLKEY, 0xDB, true, &GerudoTrainingGroundsKeys, GERUDO_TRAINING_GROUNDS_KEY_RING);
|
||||
itemTable[GERUDO_FORTRESS_KEY_RING] = Item(Text{"Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Llavero de la Fortaleza Gerudo"}, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, &GerudoFortressKeys, GERUDO_FORTRESS_KEY_RING);
|
||||
itemTable[GANONS_CASTLE_KEY_RING] = Item(Text{"Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Llavero del Castillo de Ganon"}, ITEMTYPE_SMALLKEY, 0xDD, true, &GanonsCastleKeys, GANONS_CASTLE_KEY_RING);
|
||||
|
||||
//Stones and Medallions
|
||||
itemTable[KOKIRI_EMERALD] = Item(Text{"Kokiri's Emerald", "Émeraude Kokiri", "Esmeralda de los Kokiri"}, ITEMTYPE_DUNGEONREWARD, 0xCB, true, &KokiriEmerald, KOKIRI_EMERALD);
|
||||
itemTable[GORON_RUBY] = Item(Text{"Goron's Ruby", "Rubis Goron", "Rubí de los Goron"}, ITEMTYPE_DUNGEONREWARD, 0xCC, true, &GoronRuby, GORON_RUBY);
|
||||
itemTable[ZORA_SAPPHIRE] = Item(Text{"Zora's Sapphire", "Saphir Zora", "Zafiro de los Zora"}, ITEMTYPE_DUNGEONREWARD, 0xCD, true, &ZoraSapphire, ZORA_SAPPHIRE);
|
||||
itemTable[FOREST_MEDALLION] = Item(Text{"Forest Medallion", "Médaillon de la Forêt", "Medallón del Bosque"}, ITEMTYPE_DUNGEONREWARD, 0xCE, true, &ForestMedallion, FOREST_MEDALLION);
|
||||
itemTable[FIRE_MEDALLION] = Item(Text{"Fire Medallion", "Médaillon du Feu", "Medallón del Fuego"}, ITEMTYPE_DUNGEONREWARD, 0xCF, true, &FireMedallion, FIRE_MEDALLION);
|
||||
itemTable[WATER_MEDALLION] = Item(Text{"Water Medallion", "Médaillon de l'Eau", "Medallón del Agua"}, ITEMTYPE_DUNGEONREWARD, 0xD0, true, &WaterMedallion, WATER_MEDALLION);
|
||||
itemTable[SPIRIT_MEDALLION] = Item(Text{"Spirit Medallion", "Médaillon de l'Esprit", "Medallón del Espíritu"}, ITEMTYPE_DUNGEONREWARD, 0xD1, true, &SpiritMedallion, SPIRIT_MEDALLION);
|
||||
itemTable[SHADOW_MEDALLION] = Item(Text{"Shadow Medallion", "Médaillon de l'Ombre", "Medallón de la Sombra"}, ITEMTYPE_DUNGEONREWARD, 0xD2, true, &ShadowMedallion, SHADOW_MEDALLION);
|
||||
itemTable[LIGHT_MEDALLION] = Item(Text{"Light Medallion", "Médaillon de la Lumière", "Medallón de la Luz"}, ITEMTYPE_DUNGEONREWARD, 0xD3, true, &LightMedallion, LIGHT_MEDALLION);
|
||||
|
||||
//Generic Items
|
||||
itemTable[RECOVERY_HEART] = Item(Text{"Recovery Heart", "Coeur de Vie", "Corazón"}, ITEMTYPE_ITEM, GI_HEART, false, &noVariable, RECOVERY_HEART);
|
||||
itemTable[GREEN_RUPEE] = Item(Text{"Green Rupee", "Rubis Vert", "Rupia verde"}, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, &noVariable, GREEN_RUPEE);
|
||||
itemTable[BLUE_RUPEE] = Item(Text{"Blue Rupee", "Rubis Bleu", "Rupia azul"}, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, &noVariable, BLUE_RUPEE);
|
||||
itemTable[RED_RUPEE] = Item(Text{"Red Rupee", "Rubis Rouge", "Rupia roja"}, ITEMTYPE_ITEM, GI_RUPEE_RED, false, &noVariable, RED_RUPEE);
|
||||
itemTable[PURPLE_RUPEE] = Item(Text{"Purple Rupee", "Rubis Pourpre", "Rupia morada"}, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, &noVariable, PURPLE_RUPEE);
|
||||
itemTable[HUGE_RUPEE] = Item(Text{"Huge Rupee", "Énorme Rubis", "Rupia gigante"}, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, &noVariable, HUGE_RUPEE);
|
||||
itemTable[PIECE_OF_HEART] = Item(Text{"Piece of Heart", "Quart de Coeur", "Pieza de corazón"}, ITEMTYPE_ITEM, GI_HEART_PIECE, true, &PieceOfHeart, PIECE_OF_HEART);
|
||||
itemTable[HEART_CONTAINER] = Item(Text{"Heart Container", "Réceptacle de Coeur", "Contenedor de corazón"}, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2, true, &HeartContainer, HEART_CONTAINER);
|
||||
itemTable[ICE_TRAP] = Item(Text{"Ice Trap", "Piège de Glace", "Trampa de hielo"}, ITEMTYPE_ITEM, GI_ICE_TRAP, false, &noVariable, ICE_TRAP);
|
||||
itemTable[MILK] = Item(Text{"Milk", "Lait", "Leche Lon Lon"}, ITEMTYPE_ITEM, GI_MILK, false, &noVariable, NONE);
|
||||
|
||||
//Refills
|
||||
itemTable[BOMBS_5] = Item(Text{"Bombs (5)", "Bombes (5)", "Bombas (5)"}, ITEMTYPE_REFILL, GI_BOMBS_5, false, &noVariable, BOMBS_5);
|
||||
itemTable[BOMBS_10] = Item(Text{"Bombs (10)", "Bombes (10)", "Bombas (10)"}, ITEMTYPE_REFILL, GI_BOMBS_10, false, &noVariable, BOMBS_10);
|
||||
itemTable[BOMBS_20] = Item(Text{"Bombs (20)", "Bombes (20)", "Bombas (20)"}, ITEMTYPE_REFILL, GI_BOMBS_20, false, &noVariable, BOMBS_20);
|
||||
itemTable[BOMBCHU_5] = Item(Text{"Bombchu (5)", "Missiles (5)", "Bombchus (5)"}, ITEMTYPE_REFILL, GI_BOMBCHUS_5, true, &Bombchus5, BOMBCHU_5);
|
||||
itemTable[BOMBCHU_10] = Item(Text{"Bombchu (10)", "Missiles (10)", "Bombchus (10)"}, ITEMTYPE_REFILL, GI_BOMBCHUS_10, true, &Bombchus10, BOMBCHU_10);
|
||||
itemTable[BOMBCHU_20] = Item(Text{"Bombchu (20)", "Missiles (20)", "Bombchus (20)"}, ITEMTYPE_REFILL, GI_BOMBCHUS_20, true, &Bombchus20, BOMBCHU_20);
|
||||
itemTable[BOMBCHU_DROP] = Item(Text{"Bombchu Drop", "Drop Missiles", "Bombchus"}, ITEMTYPE_DROP, GI_BOMBCHUS_10, true, &BombchuDrop, NONE);
|
||||
itemTable[ARROWS_5] = Item(Text{"Arrows (5)", "Flèches (5)", "Flechas (5)"}, ITEMTYPE_REFILL, GI_ARROWS_SMALL, false, &noVariable, ARROWS_5);
|
||||
itemTable[ARROWS_10] = Item(Text{"Arrows (10)", "Flèches (10)", "Flechas (10)"}, ITEMTYPE_REFILL, GI_ARROWS_MEDIUM, false, &noVariable, ARROWS_10);
|
||||
itemTable[ARROWS_30] = Item(Text{"Arrows (30)", "Flèches (30)", "Flechas (30)"}, ITEMTYPE_REFILL, GI_ARROWS_LARGE, false, &noVariable, ARROWS_30);
|
||||
itemTable[DEKU_NUTS_5] = Item(Text{"Deku Nuts (5)", "Noix Mojo (5)", "Nueces deku (5)"}, ITEMTYPE_REFILL, GI_NUTS_5, false, &noVariable, DEKU_NUTS_5);
|
||||
itemTable[DEKU_NUTS_10] = Item(Text{"Deku Nuts (10)", "Noix Mojo (10)", "Nueces deku (10)"}, ITEMTYPE_REFILL, GI_NUTS_10, false, &noVariable, DEKU_NUTS_10);
|
||||
itemTable[DEKU_SEEDS_30] = Item(Text{"Deku Seeds (30)", "Graines Mojo (30)", "Semillas deku (30)"}, ITEMTYPE_REFILL, GI_SEEDS_30, false, &noVariable, DEKU_SEEDS_30);
|
||||
itemTable[DEKU_STICK_1] = Item(Text{"Deku Stick (1)", "Bâton Mojo (1)", "Palo deku (1)"}, ITEMTYPE_REFILL, GI_STICKS_1, false, &noVariable, DEKU_STICK_1);
|
||||
itemTable[RED_POTION_REFILL] = Item(Text{"Red Potion Refill", "Recharge de Potion Rouge", "Recarga de poción roja"}, ITEMTYPE_REFILL, GI_POTION_RED, false, &noVariable, NONE);
|
||||
itemTable[GREEN_POTION_REFILL] = Item(Text{"Green Potion Refill", "Recharge de Potion Verte", "Recarga de poción verde"}, ITEMTYPE_REFILL, GI_POTION_GREEN, false, &noVariable, NONE);
|
||||
itemTable[BLUE_POTION_REFILL] = Item(Text{"Blue Potion Refill", "Recharge de Potion Bleue", "Recarga de poción azul"}, ITEMTYPE_REFILL, GI_POTION_BLUE, false, &noVariable, NONE);
|
||||
|
||||
//Treasure Game
|
||||
itemTable[TREASURE_GAME_HEART] = Item(Text{"Piece of Heart (Treasure Chest Minigame)", "Quart de Coeur (Chasse-aux-Trésors)", "Pieza de corazón (Cofre del Tesoro)"}, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, &PieceOfHeart, TREASURE_GAME_HEART);
|
||||
itemTable[TREASURE_GAME_GREEN_RUPEE] = Item(Text{"Green Rupee (Treasure Chest Minigame)", "Rubis Vert (Chasse-aux-Trésors)", "Rupia Verde (Cofre del Tesoro)"}, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE, false, &noVariable, TREASURE_GAME_GREEN_RUPEE);
|
||||
|
||||
//Shop Items price
|
||||
itemTable[BUY_DEKU_NUT_5] = Item(Text{"Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Comprar nueces deku (5)"}, ITEMTYPE_SHOP, 0x00, true, &Nuts, DEKU_NUTS_5, 15);
|
||||
itemTable[BUY_ARROWS_30] = Item(Text{"Buy Arrows (30)", "Acheter: Flèches (30)", "Comprar flechas (30)"}, ITEMTYPE_SHOP, 0x01, true, &BuyArrow, ARROWS_30, 60);
|
||||
itemTable[BUY_ARROWS_50] = Item(Text{"Buy Arrows (50)", "Acheter: Flèches (50)", "Comprar flechas (50)"}, ITEMTYPE_SHOP, 0x02, true, &BuyArrow, ARROWS_30, 90);
|
||||
itemTable[BUY_BOMBS_525] = Item(Text{"Buy Bombs (5) [25]", "Acheter: Bombes (5) [25]", "Comprar bombas (5) [25]"}, ITEMTYPE_SHOP, 0x03, true, &BuyBomb, BOMBS_5, 25);
|
||||
itemTable[BUY_DEKU_NUT_10] = Item(Text{"Buy Deku Nut (10)", "Acheter: Noix Mojo (10)", "Comprar Nueces deku (10)"}, ITEMTYPE_SHOP, 0x04, true, &Nuts, DEKU_NUTS_10, 30);
|
||||
itemTable[BUY_DEKU_STICK_1] = Item(Text{"Buy Deku Stick (1)", "Acheter: Bâton Mojo (1)", "Comprar palos deku (1)"}, ITEMTYPE_SHOP, 0x05, true, &Sticks, DEKU_STICK_1, 10);
|
||||
itemTable[BUY_BOMBS_10] = Item(Text{"Buy Bombs (10)", "Acheter: Bombes (10)", "Comprar Bombas (10)"}, ITEMTYPE_SHOP, 0x06, true, &BuyBomb, BOMBS_10, 50);
|
||||
itemTable[BUY_FISH] = Item(Text{"Buy Fish", "Acheter: Poisson", "Comprar pez"}, ITEMTYPE_SHOP, 0x07, true, &FishAccess, BOTTLE_WITH_FISH, 200);
|
||||
itemTable[BUY_RED_POTION_30] = Item(Text{"Buy Red Potion [30]", "Acheter: Potion Rouge [30]", "Comprar poción roja [30]"}, ITEMTYPE_SHOP, 0x08, false, &noVariable, BOTTLE_WITH_RED_POTION, 30);
|
||||
itemTable[BUY_GREEN_POTION] = Item(Text{"Buy Green Potion", "Acheter: Potion Verte", "Comprar poción verde"}, ITEMTYPE_SHOP, 0x09, true, &BuyGPotion, BOTTLE_WITH_GREEN_POTION, 30);
|
||||
itemTable[BUY_BLUE_POTION] = Item(Text{"Buy Blue Potion", "Acheter: Potion Bleue", "Comprar poción azul"}, ITEMTYPE_SHOP, 0x0A, true, &BuyBPotion, BOTTLE_WITH_BLUE_POTION, 100);
|
||||
itemTable[BUY_HYLIAN_SHIELD] = Item(Text{"Buy Hylian Shield", "Acheter: Bouclier Hylien", "Comprar escudo hyliano"}, ITEMTYPE_SHOP, 0x0C, true, &HylianShield, HYLIAN_SHIELD, 80);
|
||||
itemTable[BUY_DEKU_SHIELD] = Item(Text{"Buy Deku Shield", "Acheter: Bouclier Mojo", "Comprar escudo deku"}, ITEMTYPE_SHOP, 0x0D, true, &DekuShield, DEKU_SHIELD, 40);
|
||||
itemTable[BUY_GORON_TUNIC] = Item(Text{"Buy Goron Tunic", "Acheter: Tunique Goron", "Comprar sayo goron"}, ITEMTYPE_SHOP, 0x0E, true, &GoronTunic, GORON_TUNIC, 200);
|
||||
itemTable[BUY_ZORA_TUNIC] = Item(Text{"Buy Zora Tunic", "Acheter: Tunique Zora", "Comprar sayo zora"}, ITEMTYPE_SHOP, 0x0F, true, &ZoraTunic, ZORA_TUNIC, 300);
|
||||
itemTable[BUY_HEART] = Item(Text{"Buy Heart", "Acheter: Coeur de Vie", "Comprar corazón"}, ITEMTYPE_SHOP, 0x10, false, &noVariable, RECOVERY_HEART, 10);
|
||||
itemTable[BUY_BOMBCHU_10] = Item(Text{"Buy Bombchu (10)", "Acheter: Missiles (10)", "Comprar bombchus (10)"}, ITEMTYPE_SHOP, 0x15, true, &BuyBombchus10, BOMBCHU_10, 99);
|
||||
itemTable[BUY_BOMBCHU_20] = Item(Text{"Buy Bombchu (20)", "Acheter: Missiles (20)", "Comprar bombchus (20)"}, ITEMTYPE_SHOP, 0x16, true, &BuyBombchus20, BOMBCHU_20, 180);
|
||||
itemTable[BUY_BOMBCHU_5] = Item(Text{"Buy Bombchu (5)", "Acheter: Missiles (5)", "Comprar bombchus (5)"}, ITEMTYPE_SHOP, 0x18, true, &BuyBombchus5, BOMBCHU_5, 60);
|
||||
itemTable[BUY_DEKU_SEEDS_30] = Item(Text{"Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Comprar semillas deku (30)"}, ITEMTYPE_SHOP, 0x1D, true, &BuySeed, DEKU_SEEDS_30, 30);
|
||||
itemTable[SOLD_OUT] = Item(Text{"Sold Out", "Vendu", "Vendido"}, ITEMTYPE_SHOP, 0x26, false, &noVariable, NONE, 0);
|
||||
itemTable[BUY_BLUE_FIRE] = Item(Text{"Buy Blue Fire", "Acheter: Flamme Bleue", "Comprar fuego azul"}, ITEMTYPE_SHOP, 0x27, true, &BlueFireAccess, BOTTLE_WITH_BLUE_FIRE, 300);
|
||||
itemTable[BUY_BOTTLE_BUG] = Item(Text{"Buy Bottle Bug", "Acheter: Insecte en bouteille", "Comprar bichos"}, ITEMTYPE_SHOP, 0x28, true, &BugsAccess, BOTTLE_WITH_BUGS, 50);
|
||||
itemTable[BUY_POE] = Item(Text{"Buy Poe", "Acheter: Esprit", "Comprar Poe"}, ITEMTYPE_SHOP, 0x2A, false, &noVariable, BOTTLE_WITH_BIG_POE, 30);
|
||||
itemTable[BUY_FAIRYS_SPIRIT] = Item(Text{"Buy Fairy's Spirit", "Acheter: Esprit de Fée", "Comprar hada"}, ITEMTYPE_SHOP, 0x2B, true, &FairyAccess, BOTTLE_WITH_FAIRY, 50);
|
||||
itemTable[BUY_ARROWS_10] = Item(Text{"Buy Arrows (10)", "Acheter: Flèches (10)", "Comprar flechas (10)"}, ITEMTYPE_SHOP, 0x2C, true, &BuyArrow, ARROWS_10, 20);
|
||||
itemTable[BUY_BOMBS_20] = Item(Text{"Buy Bombs (20)", "Acheter: Bombes (20)", "Comprar bombas (20)"}, ITEMTYPE_SHOP, 0x2D, true, &BuyBomb, BOMBS_20, 80);
|
||||
itemTable[BUY_BOMBS_30] = Item(Text{"Buy Bombs (30)", "Acheter: Bombes (30)", "Comprar bombas (30)"}, ITEMTYPE_SHOP, 0x2E, true, &BuyBomb, BOMBS_20, 120);
|
||||
itemTable[BUY_BOMBS_535] = Item(Text{"Buy Bombs (5) [35]", "Acheter: Bombes (5) [35]", "Comprar bombas (5) [35]"}, ITEMTYPE_SHOP, 0x2F, true, &BuyBomb, BOMBS_5, 35);
|
||||
itemTable[BUY_RED_POTION_40] = Item(Text{"Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Comprar poción roja [40]"}, ITEMTYPE_SHOP, 0x30, false, &noVariable, BOTTLE_WITH_RED_POTION, 40);
|
||||
itemTable[BUY_RED_POTION_50] = Item(Text{"Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Comprar poción roja [50]"}, ITEMTYPE_SHOP, 0x31, false, &noVariable, BOTTLE_WITH_RED_POTION, 50);
|
||||
|
||||
itemTable[TRIFORCE] = Item(Text{"Triforce", "Triforce", "Trifuerza"}, ITEMTYPE_EVENT, GI_RUPEE_RED_LOSE, false, &noVariable, NONE);
|
||||
itemTable[HINT] = Item(Text{"Hint", "Indice", "Pista"}, ITEMTYPE_EVENT, GI_RUPEE_BLUE_LOSE, false, &noVariable, NONE);
|
||||
|
||||
// itemTable[HOOKSHOT] = Item(Text{"Hookshot", "Grappin", "Gancho"}, ITEMTYPE_ITEM, 0x80, true, &ProgressiveHookshot, HOOKSHOT);
|
||||
// itemTable[LONGSHOT] = Item(Text{"Longshot", "Super-Grappin", "Supergancho"}, ITEMTYPE_ITEM, 0x80, true, &ProgressiveHookshot, LONGSHOT);
|
||||
// itemTable[FAIRY_OCARINA] = Item(Text{"Fairy Ocarina", "Ocarina des fées", "Ocarina de las Hadas"}, ITEMTYPE_ITEM, 0x8B, true, &ProgressiveOcarina, FAIRY_OCARINA);
|
||||
// itemTable[OCARINA_OF_TIME] = Item(Text{"Ocarina of Time", "Ocarina du Temps", "Ocarina del Tiempo"}, ITEMTYPE_ITEM, 0x8B, true, &ProgressiveOcarina, OCARINA_OF_TIME);
|
||||
// itemTable[BOMB_BAG] = Item(Text{"Bomb Bag", "Sac de Bombes", "Saco de bombas"}, ITEMTYPE_ITEM, 0x82, true, &ProgressiveBombBag, BOMB_BAG);
|
||||
// itemTable[BIG_BOMB_BAG] = Item(Text{"Big Bomb Bag", "Grand Sac de Bombes", "Saco de bombas grande"}, ITEMTYPE_ITEM, 0x82, true, &ProgressiveBombBag, BIG_BOMB_BAG);
|
||||
// itemTable[BIGGEST_BOMB_BAG] = Item(Text{"Biggest Bomb Bag", "Énorme Sac de Bombes", "Saco de bombas gigante"}, ITEMTYPE_ITEM, 0x82, true, &ProgressiveBombBag, BIGGEST_BOMB_BAG);
|
||||
// itemTable[FAIRY_BOW] = Item(Text{"Fairy Bow", "Arc des Fées", "Arco de las Hadas"}, ITEMTYPE_ITEM, 0x83, true, &ProgressiveBow, FAIRY_BOW);
|
||||
// itemTable[BIG_QUIVER] = Item(Text{"Big Quiver", "Grand carquois", "Carcaj grande"}, ITEMTYPE_ITEM, 0x83, true, &ProgressiveBow, BIG_QUIVER);
|
||||
// itemTable[BIGGEST_QUIVER] = Item(Text{"Biggest Quiver", "Énorme carquois", "Carcaj gigante"}, ITEMTYPE_ITEM, 0x83, true, &ProgressiveBow, BIGGEST_QUIVER);
|
||||
// itemTable[FAIRY_SLINGSHOT] = Item(Text{"Fairy Slingshot", "Lance-Pierre des Fées", "Resortera de las hadas"}, ITEMTYPE_ITEM, 0x84, true, &ProgressiveBulletBag, FAIRY_SLINGSHOT);
|
||||
// itemTable[BIG_BULLET_BAG] = Item(Text{"Big Deku Seed Bullet Bag", "Grand sac de graines mojo", "Bolsa de semillas deku grande"}, ITEMTYPE_ITEM, 0x84, true, &ProgressiveBulletBag, BIG_BULLET_BAG);
|
||||
// itemTable[BIGGEST_BULLET_BAD] = Item(Text{"Biggest Deku Seed Bullet Bag", "Énorme sac de graines mojo", "Bolsa de semillas deku gigante"}, ITEMTYPE_ITEM, 0x84, true, &ProgressiveBulletBag, BIGGEST_BULLET_BAD);
|
||||
// itemTable[GORONS_BRACELET] = Item(Text{"Goron's Bracelet", "Bracelet Goron", "Brazalete de los Goron"}, ITEMTYPE_ITEM, 0x81, true, &ProgressiveStrength, GORONS_BRACELET);
|
||||
// itemTable[SILVER_GAUNTLETS] = Item(Text{"Silver Gauntlets", "Gantelets d'argent", "Guantes de plata"}, ITEMTYPE_ITEM, 0x81, true, &ProgressiveStrength, SILVER_GAUNTLETS);
|
||||
// itemTable[GOLDEN_GAUNTLETS] = Item(Text{"Golden Gauntlets", "Gantelets d'or", "Guantes de oro"}, ITEMTYPE_ITEM, 0x81, true, &ProgressiveStrength, GOLDEN_GAUNTLETS);
|
||||
// itemTable[SILVER_SCALE] = Item(Text{"Silver Scale", "Écaille d'argent", "Escama de Plata"}, ITEMTYPE_ITEM, 0x86, true, &ProgressiveScale, SILVER_SCALE);
|
||||
// itemTable[GOLDEN_SCALE] = Item(Text{"Golden Scale", "Écaille d'or", "Escama de Oro"}, ITEMTYPE_ITEM, 0x86, true, &ProgressiveScale, GOLDEN_SCALE);
|
||||
// itemTable[ADULT_WALLET] = Item(Text{"Adult Wallet", "Bourse d'adulte", "Bolsa de adulto"}, ITEMTYPE_ITEM, 0x85, true, &ProgressiveWallet, ADULT_WALLET);
|
||||
// itemTable[GIANT_WALLET] = Item(Text{"Giant Wallet", "Bourse de géant", "Bolsa gigante"}, ITEMTYPE_ITEM, 0x85, true, &ProgressiveWallet, GIANT_WALLET);
|
||||
// itemTable[TYCOON_WALLET] = Item(Text{"Tycoon Wallet", "Bourse de star", "Bolsa de ricachón"}, ITEMTYPE_ITEM, 0x85, true, &ProgressiveWallet, TYCOON_WALLET);
|
||||
// itemTable[DEKU_NUT_CAPACITY_30] = Item(Text{"Deku Nut Capacity (30)", "Capacité de noix Mojo (20)", "Capacidad de nueces deku (40)"}, ITEMTYPE_ITEM, 0x87, false, &noVariable, DEKU_NUT_CAPACITY_30);
|
||||
// itemTable[DEKU_NUT_CAPACITY_40] = Item(Text{"Deku Nut Capacity (40)", "Capacité de noix Mojo (30)", "Capacidad de nueces deku (50)"}, ITEMTYPE_ITEM, 0x87, false, &noVariable, DEKU_NUT_CAPACITY_40);
|
||||
// itemTable[DEKU_NUT_CAPACITY_20] = Item(Text{"Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Capacidad de palos deku (20)"}, ITEMTYPE_ITEM, 0x88, false, &noVariable, DEKU_NUT_CAPACITY_20);
|
||||
// itemTable[DEKU_NUT_CAPACITY_30] = Item(Text{"Deku Nut Capacity (30)", "Capacité de noix Mojo (20)", "Capacidad de nueces deku (40)"}, ITEMTYPE_ITEM, 0x88, false, &noVariable, DEKU_NUT_CAPACITY_30);
|
||||
// itemTable[MAGIC_METER] = Item(Text{"Magic Meter", "Jauge de Magie", "Poder mágico"}, ITEMTYPE_ITEM, 0x8A, true, &ProgressiveMagic, MAGIC_METER);
|
||||
// itemTable[ENHANCED_MAGIC_METER] = Item(Text{"Enhanced Magic Meter", "Jauge de Magie améliorée", "Poder mágico mejorado"}, ITEMTYPE_ITEM, 0x8A, true, &ProgressiveMagic, ENHANCED_MAGIC_METER);
|
||||
|
||||
}
|
||||
|
||||
Item& ItemTable(const uint32_t itemKey) {
|
||||
return itemTable[itemKey];
|
||||
}
|
||||
|
||||
//This function should only be used to place items containing hint text
|
||||
//at gossip stone locations.
|
||||
void NewItem(const uint32_t itemKey, const Item item) {
|
||||
if (itemKey <= BUY_RED_POTION_50) {
|
||||
printf("\x1b[25;0HWARNING: ATTEMPTED TO OVERWRITE ITEM %lu\n", itemKey);
|
||||
return;
|
||||
}
|
||||
|
||||
itemTable[itemKey] = item;
|
||||
}
|
8
soh/soh/Enhancements/randomizer/3drando/item_list.hpp
Normal file
8
soh/soh/Enhancements/randomizer/3drando/item_list.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "item.hpp"
|
||||
#include "keys.hpp"
|
||||
|
||||
void ItemTable_Init();
|
||||
Item& ItemTable(uint32_t itemKey);
|
||||
void NewItem(uint32_t itemKey, Item item);
|
1580
soh/soh/Enhancements/randomizer/3drando/item_location.cpp
Normal file
1580
soh/soh/Enhancements/randomizer/3drando/item_location.cpp
Normal file
File diff suppressed because it is too large
Load Diff
490
soh/soh/Enhancements/randomizer/3drando/item_location.hpp
Normal file
490
soh/soh/Enhancements/randomizer/3drando/item_location.hpp
Normal file
@ -0,0 +1,490 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "spoiler_log.hpp"
|
||||
#include "item_list.hpp"
|
||||
|
||||
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;
|
||||
uint8_t flag;
|
||||
};
|
||||
} 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(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 Biggoron(uint8_t mask) {
|
||||
return SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_BIGGORON, 0x00, mask);
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
};
|
||||
|
||||
class ItemLocation {
|
||||
public:
|
||||
ItemLocation() = default;
|
||||
ItemLocation(uint8_t scene_, ItemLocationType type_, uint8_t flag_, 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)
|
||||
: scene(scene_), type(type_), flag(flag_), 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
|
||||
key.flag = flag;
|
||||
return key;
|
||||
}
|
||||
|
||||
SpoilerCollectionCheck GetCollectionCheck() const {
|
||||
return collectionCheck;
|
||||
}
|
||||
|
||||
SpoilerCollectionCheckGroup GetCollectionCheckGroup() const {
|
||||
return collectionCheckGroup;
|
||||
}
|
||||
|
||||
uint8_t GetScene() const {
|
||||
return scene;
|
||||
}
|
||||
|
||||
uint8_t GetFlag() const {
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool IsAddedToPool() const {
|
||||
return addedToPool;
|
||||
}
|
||||
|
||||
void AddToPool() {
|
||||
addedToPool = true;
|
||||
}
|
||||
|
||||
const 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
|
||||
if (hasShopsanityPrice) {
|
||||
return;
|
||||
}
|
||||
price = price_;
|
||||
}
|
||||
|
||||
void SetShopsanityPrice(uint16_t price_) {
|
||||
price = price_;
|
||||
hasShopsanityPrice = true;
|
||||
}
|
||||
|
||||
bool HasShopsanityPrice() const {
|
||||
return hasShopsanityPrice;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const 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 SetAsHintable() {
|
||||
isHintable = true;
|
||||
}
|
||||
|
||||
void SetParentRegion(uint32_t region) {
|
||||
parentRegion = region;
|
||||
}
|
||||
|
||||
uint32_t GetParentRegionKey() const {
|
||||
return parentRegion;
|
||||
}
|
||||
|
||||
void AddExcludeOption() {
|
||||
//setting description /*--------------------------------------------------*/
|
||||
std::string_view desc = "Decide which locations you want to exclude from\n"
|
||||
"the location pool. Locations that require an item\n"
|
||||
"to be placed at them based on your current\n"
|
||||
"settings cannot be excluded and won't be shown\n"
|
||||
"unless you change your settings.\n"
|
||||
"\n"
|
||||
"If you exclude too many locations, it might not\n"
|
||||
"be possible to fill the world.";
|
||||
|
||||
//add option to forbid any location from progress items
|
||||
if (name.length() < 23) {
|
||||
excludedOption = Option::Bool(name, {"Include", "Exclude"}, {desc});
|
||||
} 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"}, {desc});
|
||||
}
|
||||
|
||||
// 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(uint8_t scene, uint8_t flag, 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{scene, ItemLocationType::Base, flag, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
|
||||
}
|
||||
|
||||
static auto Chest(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{scene, ItemLocationType::Chest, flag, std::move(name), hintKey, vanillaItem, std::move(categories), 0, SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_CHEST, scene, flag), collectionCheckGroup};
|
||||
}
|
||||
|
||||
static auto Chest(uint8_t scene, uint8_t flag, 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{scene, ItemLocationType::Chest, flag, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
|
||||
}
|
||||
|
||||
static auto Collectable(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{scene, ItemLocationType::Collectable, flag, std::move(name), hintKey, vanillaItem, std::move(categories), 0, SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE, scene, flag), collectionCheckGroup};
|
||||
}
|
||||
|
||||
static auto Collectable(uint8_t scene, uint8_t flag, 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{scene, ItemLocationType::Collectable, flag, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
|
||||
}
|
||||
|
||||
static auto GSToken(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{scene, ItemLocationType::GSToken, flag, std::move(name), hintKey, GOLD_SKULLTULA_TOKEN, std::move(categories), 0, SpoilerCollectionCheck(SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA, scene, flag), collectionCheckGroup};
|
||||
}
|
||||
|
||||
static auto GrottoScrub(uint8_t scene, uint8_t flag, 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{scene, ItemLocationType::GrottoScrub, flag, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
|
||||
}
|
||||
|
||||
static auto Delayed(uint8_t scene, uint8_t flag, 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{scene, ItemLocationType::Delayed, flag, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
|
||||
}
|
||||
|
||||
static auto Reward(uint8_t scene, uint8_t flag, 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{scene, ItemLocationType::TempleReward, flag, std::move(name), hintKey, vanillaItem, std::move(categories), 0, collectionCheck, collectionCheckGroup};
|
||||
}
|
||||
|
||||
static auto OtherHint(uint8_t scene, uint8_t flag, std::string&& name, std::vector<Category>&& categories) {
|
||||
return ItemLocation{scene, ItemLocationType::OtherHint, flag, std::move(name), NONE, NONE, std::move(categories)};
|
||||
}
|
||||
|
||||
static auto HintStone(uint8_t scene, uint8_t flag, std::string&& name, std::vector<Category>&& categories) {
|
||||
return ItemLocation{scene, ItemLocationType::HintStone, flag, std::move(name), NONE, NONE, std::move(categories)};
|
||||
}
|
||||
|
||||
void ResetVariables() {
|
||||
checked = false;
|
||||
addedToPool = false;
|
||||
placedItem = NONE;
|
||||
delayedItem = NONE;
|
||||
hintedAt = false;
|
||||
isHintable = false;
|
||||
price = 0;
|
||||
hasShopsanityPrice = false;
|
||||
hidden = false;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t scene;
|
||||
ItemLocationType type;
|
||||
uint8_t flag;
|
||||
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 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 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);
|
||||
|
||||
extern std::vector<std::vector<uint32_t>> ShopLocationLists;
|
||||
|
||||
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::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();
|
1179
soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
Normal file
1179
soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
Normal file
File diff suppressed because it is too large
Load Diff
18
soh/soh/Enhancements/randomizer/3drando/item_pool.hpp
Normal file
18
soh/soh/Enhancements/randomizer/3drando/item_pool.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "keys.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <stdint.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 GenerateItemPool();
|
||||
void AddJunk();
|
||||
|
||||
extern std::vector<uint32_t> ItemPool;
|
||||
extern std::vector<uint8_t> IceTrapModels;
|
1682
soh/soh/Enhancements/randomizer/3drando/keys.hpp
Normal file
1682
soh/soh/Enhancements/randomizer/3drando/keys.hpp
Normal file
File diff suppressed because it is too large
Load Diff
898
soh/soh/Enhancements/randomizer/3drando/location_access.cpp
Normal file
898
soh/soh/Enhancements/randomizer/3drando/location_access.cpp
Normal file
@ -0,0 +1,898 @@
|
||||
#include "location_access.hpp"
|
||||
|
||||
#include "dungeon.hpp"
|
||||
#include "item_list.hpp"
|
||||
#include "item_location.hpp"
|
||||
#include "item_pool.hpp"
|
||||
#include "logic.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "trial.hpp"
|
||||
#include "entrance.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
//generic grotto event list
|
||||
std::vector<EventAccess> grottoEvents = {
|
||||
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
|
||||
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || (CanUse(STICKS));}}),
|
||||
EventAccess(&BugShrub, {[]{return CanCutShrubs;}}),
|
||||
EventAccess(&LoneFish, {[]{return true;}}),
|
||||
};
|
||||
|
||||
//set the logic to be a specific age and time of day and see if the condition still holds
|
||||
bool LocationAccess::CheckConditionAtAgeTime(bool& age, bool& time) const {
|
||||
|
||||
IsChild = false;
|
||||
IsAdult = false;
|
||||
AtDay = false;
|
||||
AtNight = false;
|
||||
|
||||
time = true;
|
||||
age = true;
|
||||
|
||||
UpdateHelpers();
|
||||
return GetConditionsMet();
|
||||
}
|
||||
|
||||
bool LocationAccess::ConditionsMet() const {
|
||||
|
||||
Area* parentRegion = AreaTable(Location(location)->GetParentRegionKey());
|
||||
bool conditionsMet = false;
|
||||
|
||||
if ((parentRegion->childDay && CheckConditionAtAgeTime(IsChild, AtDay)) ||
|
||||
(parentRegion->childNight && CheckConditionAtAgeTime(IsChild, AtNight)) ||
|
||||
(parentRegion->adultDay && CheckConditionAtAgeTime(IsAdult, AtDay)) ||
|
||||
(parentRegion->adultNight && CheckConditionAtAgeTime(IsAdult, AtNight))) {
|
||||
conditionsMet = true;
|
||||
}
|
||||
|
||||
return conditionsMet && CanBuy();
|
||||
}
|
||||
|
||||
bool LocationAccess::CanBuy() const {
|
||||
//Not a shop location, don't need to check if buyable
|
||||
if (!(Location(location)->IsCategory(Category::cShop))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Check if wallet is large enough to buy item
|
||||
bool SufficientWallet = true;
|
||||
if (Location(location)->GetPrice() > 500) {
|
||||
SufficientWallet = ProgressiveWallet >= 3;
|
||||
} else if (Location(location)->GetPrice() > 200) {
|
||||
SufficientWallet = ProgressiveWallet >= 2;
|
||||
} else if (Location(location)->GetPrice() > 99) {
|
||||
SufficientWallet = ProgressiveWallet >= 1;
|
||||
}
|
||||
|
||||
bool OtherCondition = true;
|
||||
uint32_t placed = Location(location)->GetPlacedItemKey();
|
||||
//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 bombchus in logic, need to have found chus to buy; if not just need bomb bag
|
||||
else if (placed == BUY_BOMBCHU_5 || placed == BUY_BOMBCHU_10 || placed == 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_,
|
||||
bool timePass_,
|
||||
std::vector<EventAccess> events_,
|
||||
std::vector<LocationAccess> locations_,
|
||||
std::list<Entrance> exits_)
|
||||
: regionName(std::move(regionName_)),
|
||||
scene(std::move(scene_)),
|
||||
hintKey(hintKey_),
|
||||
timePass(timePass_),
|
||||
events(std::move(events_)),
|
||||
locations(std::move(locations_)),
|
||||
exits(std::move(exits_)) {}
|
||||
|
||||
Area::~Area() = default;
|
||||
|
||||
bool Area::UpdateEvents(SearchMode mode) {
|
||||
|
||||
if (timePass && mode != SearchMode::TimePassAccess) {
|
||||
if (Child()) {
|
||||
childDay = true;
|
||||
childNight = true;
|
||||
AreaTable(ROOT)->childDay = true;
|
||||
AreaTable(ROOT)->childNight = true;
|
||||
}
|
||||
if (Adult()) {
|
||||
adultDay = true;
|
||||
adultNight = true;
|
||||
AreaTable(ROOT)->adultDay = true;
|
||||
AreaTable(ROOT)->adultNight = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool eventsUpdated = false;
|
||||
|
||||
for (EventAccess& event : events) {
|
||||
//If the event has already happened, there's no reason to check it
|
||||
if (event.GetEvent()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((childDay && event.CheckConditionAtAgeTime(IsChild, AtDay)) ||
|
||||
(childNight && event.CheckConditionAtAgeTime(IsChild, AtNight)) ||
|
||||
(adultDay && event.CheckConditionAtAgeTime(IsAdult, AtDay)) ||
|
||||
(adultNight && event.CheckConditionAtAgeTime(IsAdult, AtNight))) {
|
||||
event.EventOccurred();
|
||||
eventsUpdated = true;
|
||||
}
|
||||
}
|
||||
return eventsUpdated;
|
||||
}
|
||||
|
||||
void Area::AddExit(uint32_t parentKey, uint32_t newExitKey, ConditionFn condition) {
|
||||
Entrance newExit = Entrance(newExitKey, {condition});
|
||||
newExit.SetParentRegion(parentKey);
|
||||
exits.push_front(newExit);
|
||||
}
|
||||
|
||||
//The exit will be completely removed from this area
|
||||
void Area::RemoveExit(Entrance* exitToRemove) {
|
||||
exits.remove_if([exitToRemove](const auto exit){return &exit == exitToRemove;});
|
||||
}
|
||||
|
||||
void Area::SetAsPrimary(uint32_t exitToBePrimary) {
|
||||
for (auto& exit : exits) {
|
||||
if (exit.Getuint32_t() == exitToBePrimary) {
|
||||
exit.SetAsPrimary();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Entrance* Area::GetExit(uint32_t exitToReturn) {
|
||||
for (auto& exit : exits) {
|
||||
if (exit.Getuint32_t() == exitToReturn) {
|
||||
return &exit;
|
||||
}
|
||||
}
|
||||
auto message = "ERROR: EXIT " + AreaTable(exitToReturn)->regionName + " DOES NOT EXIST IN " + this->regionName;
|
||||
CitraPrint(message);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Area::CanPlantBeanCheck() const {
|
||||
return (Logic::MagicBean || Logic::MagicBeanPack) && BothAgesCheck();
|
||||
}
|
||||
|
||||
bool Area::AllAccountedFor() const {
|
||||
for (const EventAccess& event : events) {
|
||||
if (!event.GetEvent()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const LocationAccess& loc : locations) {
|
||||
if (!(Location(loc.GetLocation())->IsAddedToPool())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& exit : exits) {
|
||||
if (!exit.GetConnectedRegion()->AllAccess()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return AllAccess();
|
||||
}
|
||||
|
||||
bool Area::CheckAllAccess(const uint32_t exitKey) {
|
||||
if (!AllAccess()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Entrance& exit : exits) {
|
||||
if (exit.Getuint32_t() == exitKey) {
|
||||
return exit.CheckConditionAtAgeTime(Logic::IsChild, Logic::AtDay) &&
|
||||
exit.CheckConditionAtAgeTime(Logic::IsChild, Logic::AtNight) &&
|
||||
exit.CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtDay) &&
|
||||
exit.CheckConditionAtAgeTime(Logic::IsAdult, Logic::AtNight);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Area::ResetVariables() {
|
||||
childDay = false;
|
||||
childNight = false;
|
||||
adultDay = false;
|
||||
adultNight = false;
|
||||
addedToPool = false;
|
||||
for (auto& exit : exits) {
|
||||
exit.RemoveFromPool();
|
||||
}
|
||||
}
|
||||
|
||||
std::array<Area, KEY_ENUM_MAX> areaTable;
|
||||
|
||||
bool Here(const uint32_t area, ConditionFn condition) {
|
||||
return areaTable[area].HereCheck(condition);
|
||||
}
|
||||
|
||||
bool CanPlantBean(const uint32_t area) {
|
||||
return areaTable[area].CanPlantBeanCheck();
|
||||
}
|
||||
|
||||
bool BothAges(const uint32_t area) {
|
||||
return areaTable[area].BothAgesCheck();
|
||||
}
|
||||
|
||||
bool ChildCanAccess(const uint32_t area) {
|
||||
return areaTable[area].Child();
|
||||
}
|
||||
|
||||
bool AdultCanAccess(const uint32_t area) {
|
||||
return areaTable[area].Adult();
|
||||
}
|
||||
|
||||
bool HasAccessTo(const uint32_t area) {
|
||||
return areaTable[area].HasAccess();
|
||||
}
|
||||
|
||||
|
||||
|
||||
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, {}, {}, {}));
|
||||
|
||||
//name, scene, hint text, events, locations, exits
|
||||
areaTable[ROOT] = Area("Root", "", LINKS_POCKET, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(LINKS_POCKET, {[]{return true;}})
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(ROOT_EXITS, {[]{return true;}})
|
||||
});
|
||||
|
||||
areaTable[ROOT_EXITS] = Area("Root Exits", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KF_LINKS_HOUSE, {[]{return IsChild;}}),
|
||||
Entrance(TEMPLE_OF_TIME, {[]{return (CanPlay(PreludeOfLight) && CanLeaveForest) || IsAdult;},
|
||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && PreludeOfLight && CanLeaveForest;}}),
|
||||
Entrance(SACRED_FOREST_MEADOW, {[]{return CanPlay(MinuetOfForest);},
|
||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && MinuetOfForest;}}),
|
||||
Entrance(DMC_CENTRAL_LOCAL, {[]{return CanPlay(BoleroOfFire) && CanLeaveForest;},
|
||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && BoleroOfFire && CanLeaveForest;}}),
|
||||
Entrance(LAKE_HYLIA, {[]{return CanPlay(SerenadeOfWater) && CanLeaveForest;},
|
||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && SerenadeOfWater && CanLeaveForest;}}),
|
||||
Entrance(GRAVEYARD_WARP_PAD_REGION, {[]{return CanPlay(NocturneOfShadow) && CanLeaveForest;},
|
||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && NocturneOfShadow && CanLeaveForest;}}),
|
||||
Entrance(DESERT_COLOSSUS, {[]{return CanPlay(RequiemOfSpirit) && CanLeaveForest;},
|
||||
/*Glitched*/[]{return (((IsChild && (ChildCanAccess(KOKIRI_FOREST) || ChildCanAccess(HYRULE_FIELD) || ChildCanAccess(LAKE_HYLIA))) || (IsAdult && (AdultCanAccess(KOKIRI_FOREST) || AdultCanAccess(HYRULE_FIELD) || AdultCanAccess(LAKE_HYLIA)))) && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) ||
|
||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (IsAdult || KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) && RequiemOfSpirit && CanLeaveForest;}}),
|
||||
});
|
||||
|
||||
// Overworld
|
||||
AreaTable_Init_LostWoods();
|
||||
AreaTable_Init_HyruleField();
|
||||
AreaTable_Init_CastleTown();
|
||||
AreaTable_Init_Kakariko();
|
||||
AreaTable_Init_DeathMountain();
|
||||
AreaTable_Init_ZorasDomain();
|
||||
AreaTable_Init_GerudoValley();
|
||||
// Dungeons
|
||||
AreaTable_Init_DekuTree();
|
||||
AreaTable_Init_DodongosCavern();
|
||||
AreaTable_Init_JabuJabusBelly();
|
||||
AreaTable_Init_ForestTemple();
|
||||
AreaTable_Init_FireTemple();
|
||||
AreaTable_Init_WaterTemple();
|
||||
AreaTable_Init_SpiritTemple();
|
||||
AreaTable_Init_ShadowTemple();
|
||||
AreaTable_Init_BottomOfTheWell();
|
||||
AreaTable_Init_IceCavern();
|
||||
AreaTable_Init_GerudoTrainingGrounds();
|
||||
AreaTable_Init_GanonsCastle();
|
||||
|
||||
//Set parent regions
|
||||
for (uint32_t i = ROOT; i <= GANONS_CASTLE; i++) {
|
||||
for (LocationAccess& locPair : areaTable[i].locations) {
|
||||
uint32_t location = locPair.GetLocation();
|
||||
Location(location)->SetParentRegion(i);
|
||||
}
|
||||
for (Entrance& exit : areaTable[i].exits) {
|
||||
exit.SetParentRegion(i);
|
||||
exit.SetName();
|
||||
exit.GetConnectedRegion()->entrances.push_front(&exit);
|
||||
}
|
||||
}
|
||||
/*
|
||||
//Events
|
||||
}, {
|
||||
//Locations
|
||||
}, {
|
||||
//Exits
|
||||
*/
|
||||
}
|
||||
|
||||
namespace Areas {
|
||||
|
||||
static std::array<const uint32_t, 414> allAreas = {
|
||||
ROOT,
|
||||
ROOT_EXITS,
|
||||
|
||||
KOKIRI_FOREST,
|
||||
KF_LINKS_HOUSE,
|
||||
KF_MIDOS_HOUSE,
|
||||
KF_SARIAS_HOUSE,
|
||||
KF_HOUSE_OF_TWINS,
|
||||
KF_KNOW_IT_ALL_HOUSE,
|
||||
KF_KOKIRI_SHOP,
|
||||
KF_STORMS_GROTTO,
|
||||
KF_OUTSIDE_DEKU_TREE,
|
||||
DEKU_TREE_ENTRYWAY,
|
||||
|
||||
THE_LOST_WOODS,
|
||||
LW_BRIDGE_FROM_FOREST,
|
||||
LW_BRIDGE,
|
||||
LW_FOREST_EXIT,
|
||||
LW_BEYOND_MIDO,
|
||||
LW_NEAR_SHORTCUTS_GROTTO,
|
||||
DEKU_THEATER,
|
||||
LW_SCRUBS_GROTTO,
|
||||
SFM_ENTRYWAY,
|
||||
SACRED_FOREST_MEADOW,
|
||||
SFM_WOLFOS_GROTTO,
|
||||
SFM_FAIRY_GROTTO,
|
||||
SFM_STORMS_GROTTO,
|
||||
FOREST_TEMPLE_ENTRYWAY,
|
||||
|
||||
KAKARIKO_VILLAGE,
|
||||
KAK_CARPENTER_BOSS_HOUSE,
|
||||
KAK_HOUSE_OF_SKULLTULA,
|
||||
KAK_IMPAS_HOUSE,
|
||||
KAK_IMPAS_LEDGE,
|
||||
KAK_IMPAS_HOUSE_BACK,
|
||||
KAK_IMPAS_HOUSE_NEAR_COW,
|
||||
KAK_WINDMILL,
|
||||
KAK_BAZAAR,
|
||||
KAK_SHOOTING_GALLERY,
|
||||
KAK_POTION_SHOP_FRONT,
|
||||
KAK_POTION_SHOP_BACK,
|
||||
KAK_ROOFTOP,
|
||||
KAK_BEHIND_GATE,
|
||||
KAK_BACKYARD,
|
||||
KAK_ODD_POTION_BUILDING,
|
||||
KAK_REDEAD_GROTTO,
|
||||
KAK_OPEN_GROTTO,
|
||||
BOTTOM_OF_THE_WELL_ENTRYWAY,
|
||||
|
||||
THE_GRAVEYARD,
|
||||
GRAVEYARD_DAMPES_GRAVE,
|
||||
GRAVEYARD_DAMPES_HOUSE,
|
||||
GRAVEYARD_SHIELD_GRAVE,
|
||||
GRAVEYARD_COMPOSERS_GRAVE,
|
||||
GRAVEYARD_HEART_PIECE_GRAVE,
|
||||
GRAVEYARD_WARP_PAD_REGION,
|
||||
SHADOW_TEMPLE_ENTRYWAY,
|
||||
|
||||
DEATH_MOUNTAIN_TRAIL,
|
||||
DEATH_MOUNTAIN_SUMMIT,
|
||||
DMT_OWL_FLIGHT,
|
||||
DMT_GREAT_FAIRY_FOUNTAIN,
|
||||
DMT_COW_GROTTO,
|
||||
DMT_STORMS_GROTTO,
|
||||
DODONGOS_CAVERN_ENTRYWAY,
|
||||
|
||||
DMC_UPPER_LOCAL,
|
||||
DMC_CENTRAL_LOCAL,
|
||||
DMC_LOWER_LOCAL,
|
||||
DMC_LOWER_NEARBY,
|
||||
DMC_UPPER_NEARBY,
|
||||
DMC_CENTRAL_NEARBY,
|
||||
DMC_LADDER_AREA_NEARBY,
|
||||
DMC_UPPER_GROTTO,
|
||||
DMC_HAMMER_GROTTO,
|
||||
DMC_GREAT_FAIRY_FOUNTAIN,
|
||||
FIRE_TEMPLE_ENTRYWAY,
|
||||
|
||||
GORON_CITY,
|
||||
GC_WOODS_WARP,
|
||||
GC_DARUNIAS_CHAMBER,
|
||||
GC_GROTTO_PLATFORM,
|
||||
GC_SHOP,
|
||||
GC_GROTTO,
|
||||
|
||||
ZR_FRONT,
|
||||
ZORAS_RIVER,
|
||||
ZR_BEHIND_WATERFALL,
|
||||
ZR_OPEN_GROTTO,
|
||||
ZR_FAIRY_GROTTO,
|
||||
ZR_STORMS_GROTTO,
|
||||
ZORAS_DOMAIN,
|
||||
ZD_BEHIND_KING_ZORA,
|
||||
ZD_SHOP,
|
||||
ZD_STORMS_GROTTO,
|
||||
ZORAS_FOUNTAIN,
|
||||
ZF_GREAT_FAIRY_FOUNTAIN,
|
||||
JABU_JABUS_BELLY_ENTRYWAY,
|
||||
ICE_CAVERN_ENTRYWAY,
|
||||
|
||||
HYRULE_FIELD,
|
||||
HF_SOUTHEAST_GROTTO,
|
||||
HF_OPEN_GROTTO,
|
||||
HF_INSIDE_FENCE_GROTTO,
|
||||
HF_COW_GROTTO,
|
||||
HF_NEAR_MARKET_GROTTO,
|
||||
HF_FAIRY_GROTTO,
|
||||
HF_NEAR_KAK_GROTTO,
|
||||
HF_TEKTITE_GROTTO,
|
||||
|
||||
LON_LON_RANCH,
|
||||
LLR_TALONS_HOUSE,
|
||||
LLR_STABLES,
|
||||
LLR_TOWER,
|
||||
LLR_GROTTO,
|
||||
|
||||
LAKE_HYLIA,
|
||||
LH_OWL_FLIGHT,
|
||||
LH_LAB,
|
||||
LH_FISHING_ISLAND,
|
||||
LH_FISHING_HOLE,
|
||||
LH_GROTTO,
|
||||
WATER_TEMPLE_ENTRYWAY,
|
||||
|
||||
GERUDO_VALLEY,
|
||||
GV_UPPER_STREAM,
|
||||
GV_LOWER_STREAM,
|
||||
GV_GROTTO_LEDGE,
|
||||
GV_CRATE_LEDGE,
|
||||
GV_OCTOROK_GROTTO,
|
||||
GV_FORTRESS_SIDE,
|
||||
GV_CARPENTER_TENT,
|
||||
GV_STORMS_GROTTO,
|
||||
GERUDO_FORTRESS,
|
||||
GF_OUTSIDE_GATE,
|
||||
GF_STORMS_GROTTO,
|
||||
GERUDO_TRAINING_GROUNDS_ENTRYWAY,
|
||||
|
||||
WASTELAND_NEAR_FORTRESS,
|
||||
HAUNTED_WASTELAND,
|
||||
WASTELAND_NEAR_COLOSSUS,
|
||||
DESERT_COLOSSUS,
|
||||
COLOSSUS_GREAT_FAIRY_FOUNTAIN,
|
||||
COLOSSUS_GROTTO,
|
||||
SPIRIT_TEMPLE_ENTRYWAY,
|
||||
|
||||
MARKET_ENTRANCE,
|
||||
THE_MARKET,
|
||||
MARKET_GUARD_HOUSE,
|
||||
MARKET_BAZAAR,
|
||||
MARKET_MASK_SHOP,
|
||||
MARKET_SHOOTING_GALLERY,
|
||||
MARKET_BOMBCHU_BOWLING,
|
||||
MARKET_TREASURE_CHEST_GAME,
|
||||
MARKET_POTION_SHOP,
|
||||
MARKET_BACK_ALLEY,
|
||||
MARKET_BOMBCHU_SHOP,
|
||||
MARKET_DOG_LADY_HOUSE,
|
||||
MARKET_MAN_IN_GREEN_HOUSE,
|
||||
TOT_ENTRANCE,
|
||||
TEMPLE_OF_TIME,
|
||||
TOT_BEYOND_DOOR_OF_TIME,
|
||||
|
||||
CASTLE_GROUNDS,
|
||||
HYRULE_CASTLE_GROUNDS,
|
||||
HC_GARDEN,
|
||||
HC_GREAT_FAIRY_FOUNTAIN,
|
||||
HC_STORMS_GROTTO,
|
||||
GANONS_CASTLE_GROUNDS,
|
||||
OGC_GREAT_FAIRY_FOUNTAIN,
|
||||
GANONS_CASTLE_ENTRYWAY,
|
||||
|
||||
DEKU_TREE_LOBBY,
|
||||
DEKU_TREE_2F_MIDDLE_ROOM,
|
||||
DEKU_TREE_SLINGSHOT_ROOM,
|
||||
DEKU_TREE_COMPASS_ROOM,
|
||||
DEKU_TREE_BASEMENT_LOWER,
|
||||
DEKU_TREE_BASEMENT_SCRUB_ROOM,
|
||||
DEKU_TREE_BASEMENT_WATER_ROOM,
|
||||
DEKU_TREE_BASEMENT_TORCH_ROOM,
|
||||
DEKU_TREE_BASEMENT_BACK_LOBBY,
|
||||
DEKU_TREE_BASEMENT_BACK_ROOM,
|
||||
DEKU_TREE_BASEMENT_UPPER,
|
||||
DEKU_TREE_OUTSIDE_BOSS_ROOM,
|
||||
DEKU_TREE_BOSS_ROOM,
|
||||
|
||||
DODONGOS_CAVERN_BEGINNING,
|
||||
DODONGOS_CAVERN_LOBBY,
|
||||
DODONGOS_CAVERN_LOBBY_SWITCH,
|
||||
DODONGOS_CAVERN_SE_CORRIDOR,
|
||||
DODONGOS_CAVERN_SE_ROOM,
|
||||
DODONGOS_CAVERN_NEAR_LOWER_LIZALFOS,
|
||||
DODONGOS_CAVERN_LOWER_LIZALFOS,
|
||||
DODONGOS_CAVERN_DODONGO_ROOM,
|
||||
DODONGOS_CAVERN_NEAR_DODONGO_ROOM,
|
||||
DODONGOS_CAVERN_STAIRS_LOWER,
|
||||
DODONGOS_CAVERN_STAIRS_UPPER,
|
||||
DODONGOS_CAVERN_COMPASS_ROOM,
|
||||
DODONGOS_CAVERN_ARMOS_ROOM,
|
||||
DODONGOS_CAVERN_BOMB_ROOM_LOWER,
|
||||
DODONGOS_CAVERN_2F_SIDE_ROOM,
|
||||
DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM,
|
||||
DODONGOS_CAVERN_UPPER_LIZALFOS,
|
||||
DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM,
|
||||
DODONGOS_CAVERN_BOMB_ROOM_UPPER,
|
||||
DODONGOS_CAVERN_FAR_BRIDGE,
|
||||
DODONGOS_CAVERN_BOSS_AREA,
|
||||
DODONGOS_CAVERN_BACK_ROOM,
|
||||
DODONGOS_CAVERN_BOSS_ROOM,
|
||||
|
||||
JABU_JABUS_BELLY_BEGINNING,
|
||||
JABU_JABUS_BELLY_LIFT_MIDDLE,
|
||||
JABU_JABUS_BELLY_MAIN_UPPER,
|
||||
JABU_JABUS_BELLY_MAIN_LOWER,
|
||||
JABU_JABUS_BELLY_SHABOMB_CORRIDOR,
|
||||
JABU_JABUS_BELLY_LOWER_SIDE_ROOM,
|
||||
JABU_JABUS_BELLY_LIFT_LOWER,
|
||||
JABU_JABUS_BELLY_FORKED_CORRIDOR,
|
||||
JABU_JABUS_BELLY_BOOMERANG_ROOM,
|
||||
JABU_JABUS_BELLY_MAP_ROOM,
|
||||
JABU_JABUS_BELLY_COMPASS_ROOM,
|
||||
JABU_JABUS_BELLY_BLUE_TENTACLE,
|
||||
JABU_JABUS_BELLY_GREEN_TENTACLE,
|
||||
JABU_JABUS_BELLY_BIGOCTO_ROOM,
|
||||
JABU_JABUS_BELLY_ABOVE_BIGOCTO,
|
||||
JABU_JABUS_BELLY_LIFT_UPPER,
|
||||
JABU_JABUS_BELLY_NEAR_BOSS_ROOM,
|
||||
JABU_JABUS_BELLY_BOSS_ROOM,
|
||||
|
||||
FOREST_TEMPLE_FIRST_ROOM,
|
||||
FOREST_TEMPLE_SOUTH_CORRIDOR,
|
||||
FOREST_TEMPLE_LOBBY,
|
||||
FOREST_TEMPLE_NORTH_CORRIDOR,
|
||||
FOREST_TEMPLE_LOWER_STALFOS,
|
||||
FOREST_TEMPLE_NW_OUTDOORS_LOWER,
|
||||
FOREST_TEMPLE_NW_OUTDOORS_UPPER,
|
||||
FOREST_TEMPLE_NE_OUTDOORS_LOWER,
|
||||
FOREST_TEMPLE_NE_OUTDOORS_UPPER,
|
||||
FOREST_TEMPLE_MAP_ROOM,
|
||||
FOREST_TEMPLE_SEWER,
|
||||
FOREST_TEMPLE_BELOW_BOSS_KEY_CHEST,
|
||||
FOREST_TEMPLE_FLOORMASTER_ROOM,
|
||||
FOREST_TEMPLE_WEST_CORRIDOR,
|
||||
FOREST_TEMPLE_BLOCK_PUSH_ROOM,
|
||||
FOREST_TEMPLE_NW_CORRIDOR_TWISTED,
|
||||
FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED,
|
||||
FOREST_TEMPLE_RED_POE_ROOM,
|
||||
FOREST_TEMPLE_UPPER_STALFOS,
|
||||
FOREST_TEMPLE_BLUE_POE_ROOM,
|
||||
FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED,
|
||||
FOREST_TEMPLE_NE_CORRIDOR_TWISTED,
|
||||
FOREST_TEMPLE_FROZEN_EYE_ROOM,
|
||||
FOREST_TEMPLE_FALLING_ROOM,
|
||||
FOREST_TEMPLE_GREEN_POE_ROOM,
|
||||
FOREST_TEMPLE_EAST_CORRIDOR,
|
||||
FOREST_TEMPLE_BOSS_REGION,
|
||||
FOREST_TEMPLE_BOSS_ROOM,
|
||||
|
||||
FIRE_TEMPLE_FIRST_ROOM,
|
||||
FIRE_TEMPLE_NEAR_BOSS_ROOM,
|
||||
FIRE_TEMPLE_BOSS_ROOM,
|
||||
FIRE_TEMPLE_LOOP_ENEMIES,
|
||||
FIRE_TEMPLE_LOOP_TILES,
|
||||
FIRE_TEMPLE_LOOP_FLARE_DANCER,
|
||||
FIRE_TEMPLE_LOOP_HAMMER_SWITCH,
|
||||
FIRE_TEMPLE_LOOP_GORON_ROOM,
|
||||
FIRE_TEMPLE_LOOP_EXIT,
|
||||
FIRE_TEMPLE_BIG_LAVA_ROOM,
|
||||
FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_GORON,
|
||||
FIRE_TEMPLE_BIG_LAVA_ROOM_NORTH_TILES,
|
||||
FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON,
|
||||
FIRE_TEMPLE_FIRE_PILLAR_ROOM,
|
||||
FIRE_TEMPLE_SHORTCUT_ROOM,
|
||||
FIRE_TEMPLE_SHORTCUT_CLIMB,
|
||||
FIRE_TEMPLE_BOULDER_MAZE_LOWER,
|
||||
FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM,
|
||||
FIRE_TEMPLE_EAST_CENTRAL_ROOM,
|
||||
FIRE_TEMPLE_FIRE_WALL_CHASE,
|
||||
FIRE_TEMPLE_MAP_AREA,
|
||||
FIRE_TEMPLE_BOULDER_MAZE_UPPER,
|
||||
FIRE_TEMPLE_SCARECROW_ROOM,
|
||||
FIRE_TEMPLE_EAST_PEAK,
|
||||
FIRE_TEMPLE_CORRIDOR,
|
||||
FIRE_TEMPLE_FIRE_MAZE_ROOM,
|
||||
FIRE_TEMPLE_FIRE_MAZE_UPPER,
|
||||
FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM,
|
||||
FIRE_TEMPLE_WEST_CENTRAL_LOWER,
|
||||
FIRE_TEMPLE_WEST_CENTRAL_UPPER,
|
||||
FIRE_TEMPLE_LATE_FIRE_MAZE,
|
||||
FIRE_TEMPLE_UPPER_FLARE_DANCER,
|
||||
FIRE_TEMPLE_WEST_CLIMB,
|
||||
FIRE_TEMPLE_WEST_PEAK,
|
||||
FIRE_TEMPLE_HAMMER_RETURN_PATH,
|
||||
FIRE_TEMPLE_ABOVE_FIRE_MAZE,
|
||||
|
||||
WATER_TEMPLE_LOBBY,
|
||||
WATER_TEMPLE_EAST_LOWER,
|
||||
WATER_TEMPLE_MAP_ROOM,
|
||||
WATER_TEMPLE_CRACKED_WALL,
|
||||
WATER_TEMPLE_TORCH_ROOM,
|
||||
WATER_TEMPLE_NORTH_LOWER,
|
||||
WATER_TEMPLE_BOULDERS_LOWER,
|
||||
WATER_TEMPLE_BLOCK_ROOM,
|
||||
WATER_TEMPLE_JETS_ROOM,
|
||||
WATER_TEMPLE_BOULDERS_UPPER,
|
||||
WATER_TEMPLE_BOSS_KEY_ROOM,
|
||||
WATER_TEMPLE_SOUTH_LOWER,
|
||||
WATER_TEMPLE_WEST_LOWER,
|
||||
WATER_TEMPLE_DRAGON_ROOM,
|
||||
WATER_TEMPLE_CENTRAL_PILLAR_LOWER,
|
||||
WATER_TEMPLE_CENTRAL_PILLAR_UPPER,
|
||||
WATER_TEMPLE_CENTRAL_PILLAR_BASEMENT,
|
||||
WATER_TEMPLE_EAST_MIDDLE,
|
||||
WATER_TEMPLE_WEST_MIDDLE,
|
||||
WATER_TEMPLE_HIGH_WATER,
|
||||
WATER_TEMPLE_BLOCK_CORRIDOR,
|
||||
WATER_TEMPLE_FALLING_PLATFORM_ROOM,
|
||||
WATER_TEMPLE_DRAGON_PILLARS_ROOM,
|
||||
WATER_TEMPLE_DARK_LINK_ROOM,
|
||||
WATER_TEMPLE_LONGSHOT_ROOM,
|
||||
WATER_TEMPLE_RIVER,
|
||||
WATER_TEMPLE_PRE_BOSS_ROOM,
|
||||
WATER_TEMPLE_BOSS_ROOM,
|
||||
|
||||
SPIRIT_TEMPLE_LOBBY,
|
||||
SPIRIT_TEMPLE_CHILD,
|
||||
SPIRIT_TEMPLE_CHILD_CLIMB,
|
||||
SPIRIT_TEMPLE_EARLY_ADULT,
|
||||
SPIRIT_TEMPLE_CENTRAL_CHAMBER,
|
||||
SPIRIT_TEMPLE_OUTDOOR_HANDS,
|
||||
SPIRIT_TEMPLE_BEYOND_CENTRAL_LOCKED_DOOR,
|
||||
SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR,
|
||||
SHADOW_TEMPLE_BEGINNING,
|
||||
SHADOW_TEMPLE_FIRST_BEAMOS,
|
||||
SHADOW_TEMPLE_HUGE_PIT,
|
||||
SHADOW_TEMPLE_WIND_TUNNEL,
|
||||
SHADOW_TEMPLE_BEYOND_BOAT,
|
||||
BOTTOM_OF_THE_WELL,
|
||||
BOTTOM_OF_THE_WELL_MAIN_AREA,
|
||||
ICE_CAVERN_BEGINNING,
|
||||
ICE_CAVERN_MAIN,
|
||||
GERUDO_TRAINING_GROUNDS_LOBBY,
|
||||
GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE,
|
||||
GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT,
|
||||
GERUDO_TRAINING_GROUNDS_LAVA_ROOM,
|
||||
GERUDO_TRAINING_GROUNDS_HAMMER_ROOM,
|
||||
GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER,
|
||||
GERUDO_TRAINING_GROUNDS_EYE_STATUE_UPPER,
|
||||
GERUDO_TRAINING_GROUNDS_HEAVY_BLOCK_ROOM,
|
||||
GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM,
|
||||
GANONS_CASTLE_LOBBY,
|
||||
GANONS_CASTLE_DEKU_SCRUBS,
|
||||
GANONS_CASTLE_FOREST_TRIAL,
|
||||
GANONS_CASTLE_FIRE_TRIAL,
|
||||
GANONS_CASTLE_WATER_TRIAL,
|
||||
GANONS_CASTLE_SHADOW_TRIAL,
|
||||
GANONS_CASTLE_SPIRIT_TRIAL,
|
||||
GANONS_CASTLE_LIGHT_TRIAL,
|
||||
GANONS_CASTLE_TOWER,
|
||||
DEKU_TREE_MQ_LOBBY,
|
||||
DEKU_TREE_MQ_COMPASS_ROOM,
|
||||
DEKU_TREE_MQ_BASEMENT_WATER_ROOM_FRONT,
|
||||
DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK,
|
||||
DEKU_TREE_MQ_BASEMENT_BACK_ROOM,
|
||||
DEKU_TREE_MQ_BASEMENT_LEDGE,
|
||||
DODONGOS_CAVERN_MQ_BEGINNING,
|
||||
DODONGOS_CAVERN_MQ_LOBBY,
|
||||
DODONGOS_CAVERN_MQ_LOWER_RIGHT_SIDE,
|
||||
DODONGOS_CAVERN_MQ_BOMB_BAG_AREA,
|
||||
DODONGOS_CAVERN_MQ_BOSS_AREA,
|
||||
JABU_JABUS_BELLY_MQ_BEGINNING,
|
||||
JABU_JABUS_BELLY_MQ_MAIN,
|
||||
JABU_JABUS_BELLY_MQ_DEPTHS,
|
||||
JABU_JABUS_BELLY_MQ_BOSS_AREA,
|
||||
FOREST_TEMPLE_MQ_LOBBY,
|
||||
FOREST_TEMPLE_MQ_CENTRAL_AREA,
|
||||
FOREST_TEMPLE_MQ_AFTER_BLOCK_PUZZLE,
|
||||
FOREST_TEMPLE_MQ_OUTDOOR_LEDGE,
|
||||
FOREST_TEMPLE_MQ_NW_OUTDOORS,
|
||||
FOREST_TEMPLE_MQ_NE_OUTDOORS,
|
||||
FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES,
|
||||
FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE,
|
||||
FOREST_TEMPLE_MQ_BOW_REGION,
|
||||
FOREST_TEMPLE_MQ_FALLING_ROOM,
|
||||
FOREST_TEMPLE_MQ_BOSS_REGION,
|
||||
FIRE_TEMPLE_MQ_LOWER,
|
||||
FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR,
|
||||
FIRE_TEMPLE_MQ_BIG_LAVA_ROOM,
|
||||
FIRE_TEMPLE_MQ_LOWER_MAZE,
|
||||
FIRE_TEMPLE_MQ_UPPER_MAZE,
|
||||
FIRE_TEMPLE_MQ_UPPER,
|
||||
FIRE_TEMPLE_MQ_BOSS_ROOM,
|
||||
WATER_TEMPLE_MQ_LOBBY,
|
||||
WATER_TEMPLE_MQ_DIVE,
|
||||
WATER_TEMPLE_MQ_LOWERED_WATER_LEVELS,
|
||||
WATER_TEMPLE_MQ_DARK_LINK_REGION,
|
||||
WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS,
|
||||
SPIRIT_TEMPLE_MQ_LOBBY,
|
||||
SPIRIT_TEMPLE_MQ_CHILD,
|
||||
SPIRIT_TEMPLE_MQ_ADULT,
|
||||
SPIRIT_TEMPLE_MQ_SHARED,
|
||||
SPIRIT_TEMPLE_MQ_LOWER_ADULT,
|
||||
SPIRIT_TEMPLE_MQ_BOSS_AREA,
|
||||
SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND,
|
||||
SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND,
|
||||
SHADOW_TEMPLE_MQ_ENTRYWAY,
|
||||
SHADOW_TEMPLE_MQ_BEGINNING,
|
||||
SHADOW_TEMPLE_MQ_DEAD_HAND_AREA,
|
||||
SHADOW_TEMPLE_MQ_FIRST_BEAMOS,
|
||||
SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT,
|
||||
SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT,
|
||||
SHADOW_TEMPLE_MQ_WIND_TUNNEL,
|
||||
SHADOW_TEMPLE_MQ_BEYOND_BOAT,
|
||||
SHADOW_TEMPLE_MQ_INVISIBLE_MAZE,
|
||||
BOTTOM_OF_THE_WELL_MQ,
|
||||
BOTTOM_OF_THE_WELL_MQ_PERIMETER,
|
||||
BOTTOM_OF_THE_WELL_MQ_MIDDLE,
|
||||
ICE_CAVERN_MQ_BEGINNING,
|
||||
ICE_CAVERN_MQ_MAP_ROOM,
|
||||
ICE_CAVERN_MQ_IRON_BOOTS_REGION,
|
||||
ICE_CAVERN_MQ_COMPASS_ROOM,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_LOBBY,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_LEFT_SIDE,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS,
|
||||
GERUDO_TRAINING_GROUNDS_MQ_CENTRAL_MAZE_RIGHT,
|
||||
GANONS_CASTLE_MQ_LOBBY,
|
||||
GANONS_CASTLE_MQ_DEKU_SCRUBS,
|
||||
GANONS_CASTLE_MQ_FOREST_TRIAL,
|
||||
GANONS_CASTLE_MQ_FIRE_TRIAL,
|
||||
GANONS_CASTLE_MQ_WATER_TRIAL,
|
||||
GANONS_CASTLE_MQ_SHADOW_TRIAL,
|
||||
GANONS_CASTLE_MQ_SPIRIT_TRIAL,
|
||||
GANONS_CASTLE_MQ_LIGHT_TRIAL,
|
||||
};
|
||||
|
||||
void AccessReset() {
|
||||
for (const uint32_t area : allAreas) {
|
||||
AreaTable(area)->ResetVariables();
|
||||
}
|
||||
|
||||
if(Settings::HasNightStart) {
|
||||
if(Settings::ResolvedStartingAge == AGE_CHILD) {
|
||||
AreaTable(ROOT)->childNight = true;
|
||||
} else {
|
||||
AreaTable(ROOT)->adultNight = true;
|
||||
}
|
||||
} else {
|
||||
if(Settings::ResolvedStartingAge == AGE_CHILD) {
|
||||
AreaTable(ROOT)->childDay = true;
|
||||
} else {
|
||||
AreaTable(ROOT)->adultDay = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Reset exits and clear items from locations
|
||||
void ResetAllLocations() {
|
||||
for (const uint32_t area : allAreas) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
if(Settings::HasNightStart) {
|
||||
if(Settings::ResolvedStartingAge == AGE_CHILD) {
|
||||
AreaTable(ROOT)->childNight = true;
|
||||
} else {
|
||||
AreaTable(ROOT)->adultNight = true;
|
||||
}
|
||||
} else {
|
||||
if(Settings::ResolvedStartingAge == AGE_CHILD) {
|
||||
AreaTable(ROOT)->childDay = true;
|
||||
} else {
|
||||
AreaTable(ROOT)->adultDay = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HasTimePassAccess(uint8_t age) {
|
||||
for (const uint32_t areaKey : allAreas) {
|
||||
auto area = AreaTable(areaKey);
|
||||
if (area->timePass && ((age == AGE_CHILD && area->Child()) || (age == AGE_ADULT && area->Adult()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Will dump a file which can be turned into a visual graph using graphviz
|
||||
// https://graphviz.org/download/
|
||||
// Use command: dot -Tsvg <filename> -o world.svg
|
||||
// Then open in a browser and CTRL + F to find the area of interest
|
||||
void DumpWorldGraph(std::string str) {
|
||||
std::ofstream worldGraph;
|
||||
worldGraph.open (str + ".dot");
|
||||
worldGraph << "digraph {\n\tcenter=true;\n";
|
||||
|
||||
for (const uint32_t areaKey : allAreas) {
|
||||
auto area = AreaTable(areaKey);
|
||||
for (auto exit : area->exits) {
|
||||
if (exit.GetConnectedRegion()->regionName != "Invalid Area") {
|
||||
std::string parent = exit.GetParentRegion()->regionName;
|
||||
if (area->childDay) {
|
||||
parent += " CD";
|
||||
}
|
||||
if (area->childNight) {
|
||||
parent += " CN";
|
||||
}
|
||||
if (area->adultDay) {
|
||||
parent += " AD";
|
||||
}
|
||||
if (area->adultNight) {
|
||||
parent += " AN";
|
||||
}
|
||||
Area* connected = exit.GetConnectedRegion();
|
||||
auto connectedStr = connected->regionName;
|
||||
if (connected->childDay) {
|
||||
connectedStr += " CD";
|
||||
}
|
||||
if (connected->childNight) {
|
||||
connectedStr += " CN";
|
||||
}
|
||||
if (connected->adultDay) {
|
||||
connectedStr += " AD";
|
||||
}
|
||||
if (connected->adultNight) {
|
||||
connectedStr += " AN";
|
||||
}
|
||||
worldGraph << "\t\"" + parent + "\"[shape=\"plain\"];\n";
|
||||
worldGraph << "\t\"" + connectedStr + "\"[shape=\"plain\"];\n";
|
||||
worldGraph << "\t\"" + parent + "\" -> \"" + connectedStr + "\"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
worldGraph << "}";
|
||||
worldGraph.close();
|
||||
}
|
||||
|
||||
} //namespace Areas
|
||||
|
||||
Area* AreaTable(const uint32_t areaKey) {
|
||||
if (areaKey > KEY_ENUM_MAX) {
|
||||
printf("\x1b[1;1HERROR: AREAKEY TOO BIG");
|
||||
}
|
||||
return &(areaTable[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::allAreas) {
|
||||
for (auto& exit: AreaTable(area)->exits) {
|
||||
if ((exit.GetType() == type || type == EntranceType::All) && (exit.IsPrimary() || !onlyPrimary) && exit.GetType() != EntranceType::None) {
|
||||
entrancesToShuffle.push_back(&exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
return entrancesToShuffle;
|
||||
}
|
266
soh/soh/Enhancements/randomizer/3drando/location_access.hpp
Normal file
266
soh/soh/Enhancements/randomizer/3drando/location_access.hpp
Normal file
@ -0,0 +1,266 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
#include "logic.hpp"
|
||||
#include "hint_list.hpp"
|
||||
#include "keys.hpp"
|
||||
#include "fill.hpp"
|
||||
|
||||
typedef bool (*ConditionFn)();
|
||||
|
||||
class EventAccess {
|
||||
public:
|
||||
|
||||
|
||||
explicit EventAccess(bool* event_, std::vector<ConditionFn> conditions_met_)
|
||||
: event(event_) {
|
||||
conditions_met.resize(2);
|
||||
for (size_t i = 0; i < conditions_met_.size(); i++) {
|
||||
conditions_met[i] = conditions_met_[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool ConditionsMet() const {
|
||||
if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
return true;
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHLESS)) {
|
||||
return conditions_met[0]();
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHED)) {
|
||||
if (conditions_met[0]()) {
|
||||
return true;
|
||||
} else if (conditions_met[1] != NULL) {
|
||||
return conditions_met[1]();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckConditionAtAgeTime(bool& age, bool& time) {
|
||||
|
||||
Logic::IsChild = false;
|
||||
Logic::IsAdult = false;
|
||||
Logic::AtDay = false;
|
||||
Logic::AtNight = false;
|
||||
|
||||
time = true;
|
||||
age = true;
|
||||
|
||||
Logic::UpdateHelpers();
|
||||
return ConditionsMet();
|
||||
}
|
||||
|
||||
void EventOccurred() {
|
||||
*event = true;
|
||||
}
|
||||
|
||||
bool GetEvent() const {
|
||||
return *event;
|
||||
}
|
||||
|
||||
private:
|
||||
bool* event;
|
||||
std::vector<ConditionFn> conditions_met;
|
||||
};
|
||||
|
||||
//this class is meant to hold an item location with a boolean function to determine its accessibility from a specific area
|
||||
class LocationAccess {
|
||||
public:
|
||||
|
||||
explicit LocationAccess(uint32_t location_, std::vector<ConditionFn> conditions_met_)
|
||||
: location(location_) {
|
||||
conditions_met.resize(2);
|
||||
for (size_t i = 0; i < conditions_met_.size(); i++) {
|
||||
conditions_met[i] = conditions_met_[i];
|
||||
}
|
||||
}
|
||||
|
||||
bool GetConditionsMet() const {
|
||||
if (Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
return true;
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHLESS)) {
|
||||
return conditions_met[0]();
|
||||
} else if (Settings::Logic.Is(LOGIC_GLITCHED)) {
|
||||
if (conditions_met[0]()) {
|
||||
return true;
|
||||
} else if (conditions_met[1] != NULL) {
|
||||
return conditions_met[1]();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CheckConditionAtAgeTime(bool& age, bool& time) const;
|
||||
|
||||
bool ConditionsMet() const;
|
||||
|
||||
uint32_t GetLocation() const {
|
||||
return location;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t location;
|
||||
std::vector<ConditionFn> conditions_met;
|
||||
|
||||
//Makes sure shop locations are buyable
|
||||
bool CanBuy() const;
|
||||
};
|
||||
|
||||
class Entrance;
|
||||
enum class EntranceType;
|
||||
|
||||
class Area {
|
||||
public:
|
||||
Area();
|
||||
Area(std::string regionName_, std::string scene_, uint32_t hintKey_,
|
||||
bool timePass_,
|
||||
std::vector<EventAccess> events_,
|
||||
std::vector<LocationAccess> locations_,
|
||||
std::list<Entrance> exits_);
|
||||
~Area();
|
||||
|
||||
std::string regionName;
|
||||
std::string scene;
|
||||
uint32_t hintKey;
|
||||
bool timePass;
|
||||
std::vector<EventAccess> events;
|
||||
std::vector<LocationAccess> locations;
|
||||
std::list<Entrance> exits;
|
||||
std::list<Entrance*> entrances;
|
||||
//^ The above exits are now stored in a list instead of a vector because
|
||||
//the entrance randomization algorithm plays around with pointers to these
|
||||
//entrances a lot. By putting the entrances in a list, we don't have to
|
||||
//worry about a vector potentially reallocating itself and invalidating all our
|
||||
//entrance pointers.
|
||||
|
||||
bool childDay = false;
|
||||
bool childNight = false;
|
||||
bool adultDay = false;
|
||||
bool adultNight = false;
|
||||
bool addedToPool = false;
|
||||
|
||||
bool UpdateEvents(SearchMode mode);
|
||||
|
||||
void AddExit(uint32_t parentKey, uint32_t newExitKey, ConditionFn condition);
|
||||
|
||||
void RemoveExit(Entrance* exitToRemove);
|
||||
|
||||
void SetAsPrimary(uint32_t exitToBePrimary);
|
||||
|
||||
Entrance* GetExit(uint32_t exit);
|
||||
|
||||
bool Child() const {
|
||||
return childDay || childNight;
|
||||
}
|
||||
|
||||
bool Adult() const {
|
||||
return adultDay || adultNight;
|
||||
}
|
||||
|
||||
bool BothAgesCheck() const {
|
||||
return Child() && Adult();
|
||||
}
|
||||
|
||||
bool HasAccess() const {
|
||||
return Child() || Adult();
|
||||
}
|
||||
|
||||
bool AllAccess() const {
|
||||
return childDay && childNight && adultDay && adultNight;
|
||||
}
|
||||
|
||||
//Check to see if an exit can be access as both ages at both times of day
|
||||
bool CheckAllAccess(uint32_t exitKey);
|
||||
|
||||
const HintText& GetHint() const {
|
||||
return Hint(hintKey);
|
||||
}
|
||||
|
||||
//Here checks conditional access based on whether or not both ages have
|
||||
//access to this area. For example: if there are rocks that block a path
|
||||
//which both child and adult can access, adult having hammer can give
|
||||
//both child and adult access to the path.
|
||||
bool HereCheck(ConditionFn condition) {
|
||||
|
||||
//store current age variables
|
||||
bool pastAdult = Logic::IsAdult;
|
||||
bool pastChild = Logic::IsChild;
|
||||
|
||||
//set age access as this areas ages
|
||||
Logic::IsChild = Child();
|
||||
Logic::IsAdult = Adult();
|
||||
|
||||
//update helpers and check condition as well as having at least child or adult access
|
||||
Logic::UpdateHelpers();
|
||||
bool hereVal = condition() && (Logic::IsAdult || Logic::IsChild);
|
||||
|
||||
//set back age variables
|
||||
Logic::IsChild = pastChild;
|
||||
Logic::IsAdult = pastAdult;
|
||||
Logic::UpdateHelpers();
|
||||
|
||||
return hereVal;
|
||||
}
|
||||
|
||||
bool CanPlantBeanCheck() const;
|
||||
bool AllAccountedFor() const;
|
||||
|
||||
void ResetVariables();
|
||||
|
||||
void printAgeTimeAccess() const {
|
||||
auto message = "Child Day: " + std::to_string(childDay) + "\t"
|
||||
"Child Night: " + std::to_string(childNight) + "\t"
|
||||
"Adult Day: " + std::to_string(adultDay) + "\t"
|
||||
"Adult Night: " + std::to_string(adultNight);
|
||||
CitraPrint(message);
|
||||
}
|
||||
};
|
||||
|
||||
extern std::array<Area, KEY_ENUM_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);
|
||||
|
||||
#define DAY_NIGHT_CYCLE true
|
||||
#define NO_DAY_NIGHT_CYCLE false
|
||||
|
||||
namespace Areas {
|
||||
|
||||
extern void AccessReset();
|
||||
extern void ResetAllLocations();
|
||||
extern bool HasTimePassAccess(uint8_t age);
|
||||
extern void DumpWorldGraph(std::string str);
|
||||
} //namespace Exits
|
||||
|
||||
void AreaTable_Init();
|
||||
Area* AreaTable(const uint32_t areaKey);
|
||||
std::vector<Entrance*> GetShuffleableEntrances(EntranceType type, bool onlyPrimary = true);
|
||||
|
||||
// Overworld
|
||||
void AreaTable_Init_LostWoods();
|
||||
void AreaTable_Init_HyruleField();
|
||||
void AreaTable_Init_CastleTown();
|
||||
void AreaTable_Init_Kakariko();
|
||||
void AreaTable_Init_DeathMountain();
|
||||
void AreaTable_Init_ZorasDomain();
|
||||
void AreaTable_Init_GerudoValley();
|
||||
// Dungeons
|
||||
void AreaTable_Init_DekuTree();
|
||||
void AreaTable_Init_DodongosCavern();
|
||||
void AreaTable_Init_JabuJabusBelly();
|
||||
void AreaTable_Init_ForestTemple();
|
||||
void AreaTable_Init_FireTemple();
|
||||
void AreaTable_Init_WaterTemple();
|
||||
void AreaTable_Init_SpiritTemple();
|
||||
void AreaTable_Init_ShadowTemple();
|
||||
void AreaTable_Init_BottomOfTheWell();
|
||||
void AreaTable_Init_IceCavern();
|
||||
void AreaTable_Init_GerudoTrainingGrounds();
|
||||
void AreaTable_Init_GanonsCastle();
|
@ -0,0 +1,88 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(BOTTOM_OF_THE_WELL_MAIN_AREA, {[]{return Dungeon::BottomOfTheWell.IsVanilla() && IsChild && (CanChildAttack || Nuts);},
|
||||
/*Glitched*/[]{return Dungeon::BottomOfTheWell.IsVanilla() && IsChild && CanUse(MEGATON_HAMMER);}}),
|
||||
Entrance(BOTTOM_OF_THE_WELL_MQ_PERIMETER, {[]{return Dungeon::BottomOfTheWell.IsMQ() && IsChild;},
|
||||
/*Glitched*/[]{return Dungeon::BottomOfTheWell.IsMQ() && CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::INTERMEDIATE) && Longshot;}}),
|
||||
Entrance(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, {
|
||||
//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)) && 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}),
|
||||
});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {
|
||||
//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;}}),
|
||||
//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);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(BOTTOM_OF_THE_WELL_MQ_MIDDLE, {[]{return CanPlay(ZeldasLullaby);}}),
|
||||
//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, {}, {
|
||||
//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 && HasExplosives;}}),
|
||||
//Trick: CanChildAttack && (LogicBotWMQPits || HasExplosives)
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(BOTTOM_OF_THE_WELL_MQ_PERIMETER, {[]{return true;}}),
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,265 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_CastleTown() {
|
||||
areaTable[MARKET_ENTRANCE] = Area("Market Entrance", "Market Entrance", THE_MARKET, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return IsAdult || AtDay;}}),
|
||||
Entrance(THE_MARKET, {[]{return true;}}),
|
||||
Entrance(MARKET_GUARD_HOUSE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[THE_MARKET] = Area("Market", "Market", 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;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_BACK_ALLEY] = Area("Market Back Alley", "Market", 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;}}),
|
||||
});
|
||||
|
||||
areaTable[TOT_ENTRANCE] = Area("ToT Entrance", "ToT Entrance", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_MARKET, {[]{return true;}}),
|
||||
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[TEMPLE_OF_TIME] = Area("Temple of Time", "", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(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_CLOSED) || (HasAllStones && OcarinaOfTime)));},
|
||||
/*Glitched*/[]{return SongOfTime && OpenDoorOfTime.Is(OPENDOOROFTIME_CLOSED) && (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::ADVANCED) ||
|
||||
((Bugs || Fish) && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE)));}}),
|
||||
});
|
||||
|
||||
areaTable[TOT_BEYOND_DOOR_OF_TIME] = Area("Beyond Door of Time", "", TEMPLE_OF_TIME, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
//EventAccess(&TimeTravel, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(SHEIK_AT_TEMPLE, {[]{return ForestMedallion && IsAdult;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(TEMPLE_OF_TIME, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[CASTLE_GROUNDS] = Area("Castle Grounds", "Castle Grounds", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(THE_MARKET, {[]{return true;}}),
|
||||
Entrance(HYRULE_CASTLE_GROUNDS, {[]{return IsChild;}}),
|
||||
Entrance(GANONS_CASTLE_GROUNDS, {[]{return IsAdult;}}),
|
||||
});
|
||||
|
||||
areaTable[HYRULE_CASTLE_GROUNDS] = Area("Hyrule Castle Grounds", "Castle Grounds", HYRULE_CASTLE, DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
|
||||
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
|
||||
Entrance(HC_GARDEN, {[]{return WeirdEgg || !ShuffleWeirdEgg;}}),
|
||||
Entrance(HC_GREAT_FAIRY_FOUNTAIN, {[]{return CanBlastOrSmash;},
|
||||
/*Glitched*/[]{return Sticks && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
|
||||
Entrance(HC_STORMS_GROTTO, {[]{return CanOpenStormGrotto;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
||||
});
|
||||
|
||||
areaTable[HC_GARDEN] = Area("HC Garden", "Castle Grounds", HYRULE_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(HC_ZELDAS_LETTER, {[]{return true;}}),
|
||||
LocationAccess(SONG_FROM_IMPA, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_CASTLE_GROUNDS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[HC_GREAT_FAIRY_FOUNTAIN] = Area("HC Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(HC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[HC_STORMS_GROTTO] = Area("HC Storms Grotto", "", 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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
LocationAccess(HC_STORMS_GROTTO_GOSSIP_STONE, {[]{return CanBlastOrSmash;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GANONS_CASTLE_GROUNDS] = Area("Ganon's Castle Grounds", "Castle Grounds", OUTSIDE_GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations //the terrain was lowered such that you can't get this GS with a simple sword slash
|
||||
LocationAccess(OGC_GS, {[]{return HasExplosives || (IsAdult && (LogicOutsideGanonsGS || Bow || HookshotOrBoomerang || CanUse(DINS_FIRE)));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(CASTLE_GROUNDS, {[]{return AtNight;}}),
|
||||
Entrance(OGC_GREAT_FAIRY_FOUNTAIN, {[]{return CanUse(GOLDEN_GAUNTLETS) && AtNight;}}),
|
||||
Entrance(GANONS_CASTLE_ENTRYWAY, {[]{return CanBuildRainbowBridge;},
|
||||
/*Glitched*/[]{return (HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::ADVANCED) || (HoverBoots && CanShield && Bombs && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::EXPERT)) || (HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::ADVANCED));}}),
|
||||
});
|
||||
|
||||
areaTable[OGC_GREAT_FAIRY_FOUNTAIN] = Area("OGC Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(OGC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(CASTLE_GROUNDS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_GUARD_HOUSE] = Area("Market Guard House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(MARKET_10_BIG_POES, {[]{return IsAdult && BigPoeKill;}}),
|
||||
LocationAccess(MARKET_GS_GUARD_HOUSE, {[]{return IsChild;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(MARKET_ENTRANCE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_BAZAAR] = Area("Market Bazaar", "", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_MARKET, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_MASK_SHOP] = Area("Market Mask Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&SkullMask, {[]{return SkullMask || (ZeldasLetter && (CompleteMaskQuest || ChildCanAccess(KAKARIKO_VILLAGE)));}}),
|
||||
EventAccess(&MaskOfTruth, {[]{return MaskOfTruth || (SkullMask && (CompleteMaskQuest || (ChildCanAccess(THE_LOST_WOODS) && CanPlay(SariasSong) && AreaTable(THE_GRAVEYARD)->childDay && ChildCanAccess(HYRULE_FIELD) && HasAllStones)));}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(THE_MARKET, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_SHOOTING_GALLERY] = Area("Market Shooting Gallery", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(MARKET_SHOOTING_GALLERY_REWARD, {[]{return IsChild;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_MARKET, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_BOMBCHU_BOWLING] = Area("Market Bombchu Bowling", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, {[]{return CanPlayBowling;}}),
|
||||
LocationAccess(MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, {[]{return CanPlayBowling;}}),
|
||||
LocationAccess(MARKET_BOMBCHU_BOWLING_BOMBCHUS, {[]{return CanPlayBowling;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_MARKET, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_POTION_SHOP] = Area("Market Potion Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(MARKET_POTION_SHOP_ITEM_1, {[]{return true;}}),
|
||||
LocationAccess(MARKET_POTION_SHOP_ITEM_2, {[]{return true;}}),
|
||||
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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_MARKET, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_TREASURE_CHEST_GAME] = Area("Market Treasure Chest Game", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(MARKET_TREASURE_CHEST_GAME_REWARD, {[]{return (CanUse(LENS_OF_TRUTH) && !ShuffleChestMinigame) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 6)) || (ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK) && SmallKeys(MARKET_TREASURE_CHEST_GAME, 1));},
|
||||
/*Glitched*/[]{return !ShuffleChestMinigame && (CanUse(FARORES_WIND) && (HasBottle || WeirdEgg) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE));}}),
|
||||
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);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_MARKET, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_BOMBCHU_SHOP] = Area("Market Bombchu Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_1, {[]{return true;}}),
|
||||
LocationAccess(MARKET_BOMBCHU_SHOP_ITEM_2, {[]{return true;}}),
|
||||
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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_DOG_LADY_HOUSE] = Area("Market Dog Lady House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(MARKET_LOST_DOG, {[]{return IsChild && AtNight;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[MARKET_MAN_IN_GREEN_HOUSE] = Area("Market Man in Green House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(MARKET_BACK_ALLEY, {[]{return true;}}),
|
||||
});
|
||||
}
|
@ -0,0 +1,293 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
|
||||
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, {
|
||||
//Events
|
||||
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(DEATH_MOUNTAIN_TRAIL) && CanPlay(SongOfStorms) && (HasExplosives || GoronBracelet));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(DMT_CHEST, {[]{return CanBlastOrSmash || (LogicDMTBombable && IsChild && GoronBracelet);},
|
||||
/*Glitched*/[]{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
|
||||
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;},
|
||||
/*Glitched*/[]{return (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));}}),
|
||||
LocationAccess(DMT_GS_ABOVE_DODONGOS_CAVERN, {[]{return IsAdult && AtNight && CanUse(MEGATON_HAMMER) && CanGetNightTimeGS;},
|
||||
/*Glitched*/[]{return IsAdult && AtNight && CanGetNightTimeGS && CanUse(STICKS) && ((CanTakeDamageTwice && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));}}),
|
||||
}, {
|
||||
//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 && LogicDMTSummitHover)));},
|
||||
/*Glitched*/[]{return IsAdult && Here(DEATH_MOUNTAIN_TRAIL, []{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}}),
|
||||
Entrance(DODONGOS_CAVERN_ENTRYWAY, {[]{return HasExplosives || GoronBracelet || IsAdult;}}),
|
||||
Entrance(DMT_STORMS_GROTTO, {[]{return CanOpenStormGrotto;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
||||
});
|
||||
|
||||
areaTable[DEATH_MOUNTAIN_SUMMIT] = Area("Death Mountain Summit", "Death Mountain", 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) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(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;});},
|
||||
/*Glitched*/[]{return Here(DEATH_MOUNTAIN_SUMMIT, []{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}}),
|
||||
Entrance(DMT_GREAT_FAIRY_FOUNTAIN, {[]{return Here(DEATH_MOUNTAIN_SUMMIT, []{return CanBlastOrSmash;});},
|
||||
/*Glitched*/[]{return ((KokiriSword || Sticks || IsAdult) && CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::ADVANCED)) || (IsChild && CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::EXPERT));}}),
|
||||
});
|
||||
|
||||
areaTable[DMT_OWL_FLIGHT] = Area("DMT Owl Flight", "Death Mountain", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KAK_IMPAS_LEDGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DMT_COW_GROTTO] = Area("DMT Cow Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DMT_COW_GROTTO_COW, {[]{return CanPlay(EponasSong);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && EponasSong;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}),
|
||||
|
||||
});
|
||||
|
||||
areaTable[DMT_STORMS_GROTTO] = Area("DMT Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||
//Locations
|
||||
LocationAccess(DMT_STORMS_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(DMT_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DMT_GREAT_FAIRY_FOUNTAIN] = Area("DMT Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DMT_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DEATH_MOUNTAIN_SUMMIT, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GORON_CITY] = Area("Goron City", "Goron City", 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));},
|
||||
/*Glitched*/[]{return IsChild && CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
EventAccess(&GCWoodsWarpOpen, {[]{return GCWoodsWarpOpen || (CanBlastOrSmash || CanUse(DINS_FIRE) || CanUse(BOW) || GoronBracelet || GoronCityChildFire);},
|
||||
/*Glitched*/[]{return (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));}}),
|
||||
EventAccess(&GCDaruniasDoorOpenChild, {[]{return GCDaruniasDoorOpenChild || (IsChild && CanPlay(ZeldasLullaby));},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && ZeldasLullaby;}}),
|
||||
EventAccess(&StopGCRollingGoronAsAdult, {[]{return StopGCRollingGoronAsAdult || (IsAdult && (GoronBracelet || HasExplosives || Bow || (LogicLinkGoronDins && CanUse(DINS_FIRE))));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GC_MAZE_LEFT_CHEST, {[]{return CanUse(MEGATON_HAMMER) || CanUse(SILVER_GAUNTLETS) || (LogicGoronCityLeftMost && HasExplosives && CanUse(HOVER_BOOTS));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE);}}),
|
||||
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;}}),
|
||||
}, {
|
||||
//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)));},
|
||||
/*Glitched*/[]{return IsChild && Sticks && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
|
||||
Entrance(GC_DARUNIAS_CHAMBER, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || GCDaruniasDoorOpenChild;}}),
|
||||
Entrance(GC_GROTTO, {[]{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)));},
|
||||
/*Glitched*/[]{return (HasBombchus && ((IsChild && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE))) || (IsChild && CanUse(LONGSHOT));}}),
|
||||
});
|
||||
|
||||
areaTable[GC_WOODS_WARP] = Area("GC Woods Warp", "Goron City", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&GCWoodsWarpOpen, {[]{return GCWoodsWarpOpen || (CanBlastOrSmash || CanUse(DINS_FIRE));}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(GORON_CITY, {[]{return CanLeaveForest && GCWoodsWarpOpen;}}),
|
||||
Entrance(THE_LOST_WOODS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GC_DARUNIAS_CHAMBER] = Area("GC Darunias Chamber", "Goron City", GORON_CITY, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&GoronCityChildFire, {[]{return GoronCityChildFire || (IsChild && CanUse(STICKS));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GC_DARUNIAS_JOY, {[]{return IsChild && CanPlay(SariasSong);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && ((Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2))) || GCDaruniasDoorOpenChild) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && SariasSong;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GORON_CITY, {[]{return true;}}),
|
||||
Entrance(DMC_LOWER_LOCAL, {[]{return IsAdult;},
|
||||
/*Glitched*/[]{return IsChild && GCDaruniasDoorOpenChild && (KokiriSword || Sticks) && GlitchOccamsStatue;}}),
|
||||
});
|
||||
|
||||
areaTable[GC_GROTTO_PLATFORM] = Area("GC Grotto Platform", "Goron City", 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));}}),
|
||||
});
|
||||
|
||||
areaTable[GC_SHOP] = Area("GC Shop", "", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GORON_CITY, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GC_GROTTO] = Area("GC Grotto", "", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GC_GROTTO_PLATFORM, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DMC_UPPER_NEARBY] = Area("DMC Upper Nearby", "Death Mountain Crater", 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);});},
|
||||
/*Glitched*/[]{return Here(DMC_UPPER_NEARBY, []{return CanUse(STICKS) && FireTimer >= 48 && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}})
|
||||
});
|
||||
|
||||
areaTable[DMC_UPPER_LOCAL] = Area("DMC Upper Local", "Death Mountain Crater", 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);}}),
|
||||
}, {
|
||||
//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));},
|
||||
/*Glitched*/[]{return FireTimer >= 24 && CanTakeDamage && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE);}}),
|
||||
Entrance(DMC_LOWER_NEARBY, {[]{return false;},
|
||||
/*Glitched*/[]{return FireTimer >= 24 && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
|
||||
areaTable[DMC_LADDER_AREA_NEARBY] = Area("DMC Ladder Area Nearby", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DMC_DEKU_SCRUB, {[]{return IsChild && CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DMC_UPPER_NEARBY, {[]{return Hearts >= 3;}}),
|
||||
Entrance(DMC_LOWER_NEARBY, {[]{return Hearts >= 3 && (CanUse(HOVER_BOOTS) || (LogicCraterUpperToLower && IsAdult && CanUse(MEGATON_HAMMER)));}}),
|
||||
});
|
||||
|
||||
areaTable[DMC_LOWER_NEARBY] = Area("DMC Lower Nearby", "Death Mountain Crater", 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);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) || (FireTimer >= 48 && CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE) && (CanTakeDamageTwice || CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED))) ||
|
||||
(Bombs && CanShield && FireTimer >= 48 && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::EXPERT)) || Here(DMC_UPPER_LOCAL, []{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::ADVANCED);});}}),
|
||||
Entrance(DMC_HAMMER_GROTTO, {[]{return IsAdult && CanUse(MEGATON_HAMMER);},
|
||||
/*Glitched*/[]{return IsAdult && FireTimer >= 48 && CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE) && (CanTakeDamageTwice || CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));}}),
|
||||
});
|
||||
|
||||
areaTable[DMC_LOWER_LOCAL] = Area("DMC Lower Local", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(DMC_LOWER_NEARBY, {[]{return true;}}),
|
||||
Entrance(DMC_LADDER_AREA_NEARBY, {[]{return true;}}),
|
||||
Entrance(DMC_CENTRAL_NEARBY, {[]{return (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT)) && (FireTimer >= 8 || Hearts >= 3);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) && (FireTimer >= 8 || Hearts >= 3);}}),
|
||||
Entrance(DMC_CENTRAL_LOCAL, {[]{return (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT)) && FireTimer >= 24;}}),
|
||||
});
|
||||
|
||||
areaTable[DMC_CENTRAL_NEARBY] = Area("DMC Central Nearby", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DMC_VOLCANO_FREESTANDING_POH, {[]{return IsAdult && Hearts >= 3 && (CanPlantBean(DMC_CENTRAL_LOCAL) || (LogicCraterBeanPoHWithHovers && HoverBoots));},
|
||||
/*Glitched*/[]{return Here(DMC_LOWER_LOCAL, []{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) && FireTimer >= 24;});}}),
|
||||
LocationAccess(SHEIK_IN_CRATER, {[]{return IsAdult && (FireTimer >= 8 || Hearts >= 3);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DMC_CENTRAL_LOCAL, {[]{return FireTimer >= 48;}}),
|
||||
});
|
||||
|
||||
areaTable[DMC_CENTRAL_LOCAL] = Area("DMC Central Local", "Death Mountain Crater", DEATH_MOUNTAIN_CRATER, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(DMC_CENTRAL_LOCAL) && CanPlay(SongOfStorms));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(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);},
|
||||
/*Glitched*/[]{return IsChild && Hearts >= 3 && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE);}}),
|
||||
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);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) && FireTimer >= 48;}}),
|
||||
});
|
||||
|
||||
areaTable[DMC_GREAT_FAIRY_FOUNTAIN] = Area("DMC Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DMC_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanTakeDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DMC_LOWER_LOCAL, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DMC_UPPER_GROTTO] = Area("DMC Upper Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||
//Locations
|
||||
LocationAccess(DMC_UPPER_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(DMC_UPPER_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DMC_UPPER_LOCAL, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DMC_HAMMER_GROTTO] = Area("DMC Hammer Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DMC_DEKU_SCRUB_GROTTO_LEFT, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(DMC_DEKU_SCRUB_GROTTO_RIGHT, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(DMC_DEKU_SCRUB_GROTTO_CENTER, {[]{return CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DMC_LOWER_LOCAL, {[]{return true;}}),
|
||||
});
|
||||
}
|
@ -0,0 +1,266 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_DekuTree() {
|
||||
/*--------------------------
|
||||
| VANILLA/MQ DECIDER |
|
||||
---------------------------*/
|
||||
areaTable[DEKU_TREE_ENTRYWAY] = Area("Deku Tree Entryway", "Deku Tree", 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;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::DekuTree.IsVanilla()) {
|
||||
areaTable[DEKU_TREE_LOBBY] = Area("Deku Tree Lobby", "Deku Tree", 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);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(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;});},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return false;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE);}}),
|
||||
Entrance(DEKU_TREE_BOSS_ROOM, {[]{return false;},
|
||||
/*Glitched*/[]{return IsChild && CanUse(KOKIRI_SWORD) && Nuts && CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::EXPERT);}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_2F_MIDDLE_ROOM] = Area("Deku Tree 2F Middle Room", "Deku Tree", 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);});}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_SLINGSHOT_ROOM] = Area("Deku Tree Slingshot Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DEKU_TREE_SLINGSHOT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(DEKU_TREE_SLINGSHOT_ROOM_SIDE_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DEKU_TREE_2F_MIDDLE_ROOM, {[]{return CanUse(SLINGSHOT) || CanUse(HOVER_BOOTS);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_COMPASS_ROOM] = Area("Deku Tree Compass Room", "Deku Tree", 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);}}),
|
||||
}, {
|
||||
//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;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DEKU_TREE_LOBBY, {[]{return HasFireSourceWithTorch || CanUse(BOW);}}),
|
||||
Entrance(DEKU_TREE_BOSS_ROOM, {[]{return false;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED);}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_BASEMENT_LOWER] = Area("Deku Tree Basement Lower", "Deku Tree", 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);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(DEKU_TREE_BASEMENT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(DEKU_TREE_GS_BASEMENT_GATE, {[]{return IsAdult || CanChildAttack;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
LocationAccess(DEKU_TREE_GS_BASEMENT_VINES, {[]{return CanUseProjectile || CanUse(DINS_FIRE) || (LogicDekuBasementGS && (IsAdult || Sticks || KokiriSword));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE);}}),
|
||||
}, {
|
||||
//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);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE);}}),
|
||||
Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return false;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_BASEMENT_SCRUB_ROOM] = Area("Deku Tree Basement Scrub Room", "Deku Tree", 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);});}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_BASEMENT_WATER_ROOM] = Area("Deku Tree Basement Water Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(DEKU_TREE_BASEMENT_SCRUB_ROOM, {[]{return true;}}),
|
||||
Entrance(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, {
|
||||
//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);}}),
|
||||
}, {}, {
|
||||
//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);});}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_BASEMENT_BACK_LOBBY] = Area("Deku Tree Basement Back Lobby", "Deku Tree", 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)));},
|
||||
/*Glitched*/[]{return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, []{return HasFireSourceWithTorch || CanUse(BOW);}) && CanUse(MEGATON_HAMMER);}}),
|
||||
}, {}, {
|
||||
//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;});},
|
||||
/*Glitched*/[]{return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, []{return HasFireSourceWithTorch || CanUse(Bow);}) &&
|
||||
Here(DEKU_TREE_BASEMENT_BACK_LOBBY, []{return (GlitchBlueFireWall && BlueFire) || (CanUse(STICKS) && CanTakeDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::EXPERT));});}}),
|
||||
Entrance(DEKU_TREE_BASEMENT_UPPER, {[]{return Here(DEKU_TREE_BASEMENT_BACK_LOBBY, []{return HasFireSourceWithTorch || CanUse(Bow);}) && IsChild;}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_BASEMENT_BACK_ROOM] = Area("Deku Tree Basement Back Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DEKU_TREE_GS_BASEMENT_BACK_ROOM, {[]{return HookshotOrBoomerang;},
|
||||
/*Glitched*/[]{return Bombs && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {
|
||||
//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);}}),
|
||||
}, {}, {
|
||||
//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));});}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_OUTSIDE_BOSS_ROOM] = Area("Deku Tree Outside Boss Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(DEKU_TREE_BASEMENT_UPPER, {[]{return true;}}),
|
||||
Entrance(DEKU_TREE_BOSS_ROOM, {[]{return Here(DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return HasShield;});}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_BOSS_ROOM] = Area("Deku Tree Boss Room", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&DekuTreeClear, {[]{return DekuTreeClear || ((IsAdult || KokiriSword || Sticks) && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || HookshotOrBoomerang));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(QUEEN_GOHMA, {[]{return DekuTreeClear;}}),
|
||||
LocationAccess(DEKU_TREE_QUEEN_GOHMA_HEART, {[]{return DekuTreeClear;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DEKU_TREE_OUTSIDE_BOSS_ROOM, {[]{return true;}}),
|
||||
Entrance(DEKU_TREE_ENTRYWAY, {[]{return DekuTreeClear;}}),
|
||||
});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {
|
||||
//Events
|
||||
EventAccess(&DekuBabaSticks, {[]{return DekuBabaSticks || (IsAdult || KokiriSword || Boomerang);}}),
|
||||
EventAccess(&DekuBabaNuts, {[]{return DekuBabaNuts || (IsAdult || KokiriSword || Slingshot || Sticks || HasExplosives || CanUse(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;}}),
|
||||
}, {
|
||||
//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;});}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_MQ_COMPASS_ROOM] = Area("Deku Tree MQ Compass Room", "Deku Tree", 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 ||
|
||||
(Bombs && (CanPlay(SongOfTime) || IsAdult)) ||
|
||||
(IsAdult && CanUse(MEGATON_HAMMER) && (CanPlay(SongOfTime) /*|| LogicDekuMQCompassGS*/));});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(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;}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_MQ_BASEMENT_WATER_ROOM_BACK] = Area("Deku Tree MQ Basement Water Room Front", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(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;}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_MQ_BASEMENT_BACK_ROOM] = Area("Deku Tree MQ Basement Back Room", "Deku Tree", 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;}}),
|
||||
}, {
|
||||
//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)));}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_TREE_MQ_BASEMENT_LEDGE] = Area("Deku Tree MQ Basement Ledge", "Deku Tree", DEKU_TREE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&DekuTreeClear, {[]{return DekuTreeClear || (Here(DEKU_TREE_MQ_BASEMENT_LEDGE, []{return HasFireSourceWithTorch;}) &&
|
||||
Here(DEKU_TREE_MQ_BASEMENT_LEDGE, []{return HasShield;}) &&
|
||||
(IsAdult || KokiriSword || Sticks) && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || HookshotOrBoomerang));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(DEKU_TREE_MQ_DEKU_SCRUB, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(DEKU_TREE_QUEEN_GOHMA_HEART, {[]{return HasFireSourceWithTorch && HasShield && (IsAdult || KokiriSword || Sticks) && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || HookshotOrBoomerang);}}),
|
||||
LocationAccess(QUEEN_GOHMA, {[]{return HasFireSourceWithTorch && HasShield && (IsAdult || KokiriSword || Sticks) && (Nuts || CanUse(SLINGSHOT) || CanUse(BOW) || HookshotOrBoomerang);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DEKU_TREE_MQ_BASEMENT_BACK_ROOM, {[]{return IsChild;}}),
|
||||
Entrance(DEKU_TREE_MQ_LOBBY, {[]{return true;}}),
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,319 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_DodongosCavern() {
|
||||
/*--------------------------
|
||||
| VANILLA/MQ DECIDER |
|
||||
---------------------------*/
|
||||
areaTable[DODONGOS_CAVERN_ENTRYWAY] = Area("Dodongos Cavern Entryway", "Dodongos Cavern", 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;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::DodongosCavern.IsVanilla()) {
|
||||
areaTable[DODONGOS_CAVERN_BEGINNING] = Area("Dodongos Cavern Beginning", "Dodongos Cavern", 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;});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_BEGINNING, []{return GlitchBlueFireWall && BlueFire;});}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_LOBBY] = Area("Dodongos Cavern Lobby", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || (CanSummonGossipFairy && Here(DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;}));},
|
||||
/*Glitched*/[]{return CanSummonGossipFairy && Here(DODONGOS_CAVERN_LOBBY, []{return GlitchBlueFireWall && BlueFire;});}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_MAP_CHEST, {[]{return Here(DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_LOBBY, []{return (GlitchBlueFireWall && BlueFire) || (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));}) || CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);}}),
|
||||
LocationAccess(DODONGOS_CAVERN_DEKU_SCRUB_LOBBY, {[]{return CanStunDeku || GoronBracelet;}}),
|
||||
LocationAccess(DODONGOS_CAVERN_GOSSIP_STONE, {[]{return Here(DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_LOBBY, []{return (GlitchBlueFireWall && BlueFire) || (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_BEGINNING, {[]{return true;}}),
|
||||
Entrance(DODONGOS_CAVERN_LOBBY_SWITCH, {[]{return IsAdult;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) || (HasExplosives && (CanUse(SLINGSHOT) || CanUse(HOOKSHOT) || CanUse(BOW)) && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)) || (CanShield && GoronBracelet && GlitchModernHalfie) || ((KokiriSword || Sticks || CanUse(MEGATON_HAMMER)) && (Bombs || GoronBracelet) && Fairy && GlitchClassicHalfie);}}),
|
||||
Entrance(DODONGOS_CAVERN_SE_CORRIDOR, {[]{return Here(DODONGOS_CAVERN_LOBBY, []{return CanBlastOrSmash || GoronBracelet;});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_LOBBY, []{return (GlitchBlueFireWall && BlueFire) || (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));});}}),
|
||||
Entrance(DODONGOS_CAVERN_STAIRS_LOWER, {[]{return HasAccessTo(DODONGOS_CAVERN_LOBBY_SWITCH);}}),
|
||||
Entrance(DODONGOS_CAVERN_FAR_BRIDGE, {[]{return HasAccessTo(DODONGOS_CAVERN_FAR_BRIDGE);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(DODONGOS_CAVERN_BOSS_AREA, {[]{return Here(DODONGOS_CAVERN_FAR_BRIDGE, []{return HasExplosives;});}}),
|
||||
Entrance(DODONGOS_CAVERN_BOSS_ROOM, {[]{return false;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED);}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_LOBBY_SWITCH] = Area("Dodongos Cavern Lobby Switch", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
|
||||
Entrance(DODONGOS_CAVERN_DODONGO_ROOM, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_SE_CORRIDOR] = Area("Dodongos Cavern SE Corridor", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_GS_SCARECROW, {[]{return CanUse(SCARECROW) || (IsAdult && CanUse(LONGSHOT)) || (LogicDCScarecrowGS && (IsAdult || CanChildAttack));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || (CanUse(LONGSHOT) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
|
||||
Entrance(DODONGOS_CAVERN_SE_ROOM, {[]{return Here(DODONGOS_CAVERN_SE_CORRIDOR, []{return CanBlastOrSmash || IsAdult || CanChildAttack || (CanTakeDamage && CanShield);});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_SE_CORRIDOR, []{return (GlitchBlueFireWall && BlueFire);});}}),
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS, {[]{return IsAdult || CanChildAttack;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_SE_CORRIDOR, {[]{return true;}}),
|
||||
Entrance(DODONGOS_CAVERN_LOWER_LIZALFOS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_LOWER_LIZALFOS] = Area("Dodongos Cavern Lower Lizalfos", "Dodongos Cavern", 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;});},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
Entrance(DODONGOS_CAVERN_DODONGO_ROOM, {[]{return Here(DODONGOS_CAVERN_LOWER_LIZALFOS, []{return IsAdult || Slingshot || Sticks || KokiriSword || HasExplosives;});},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_DODONGO_ROOM] = Area("Dodongos Cavern Dodongo Room", "Dodongos Cavern", 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;});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_DODONGO_ROOM, []{return GlitchBlueFireWall && BlueFire;});}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_NEAR_DODONGO_ROOM] = Area("Dodongos Cavern Near Dodongo Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_DEKU_SCRUB_SIDE_ROOM_NEAR_DODONGOS, {[]{return CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_DODONGO_ROOM, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_STAIRS_LOWER] = Area("Dodongos Cavern Stairs Lower", "Dodongos Cavern", 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;});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_STAIRS_LOWER, []{return GlitchBlueFireWall && BlueFire;});}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_STAIRS_UPPER] = Area("Dodongos Cavern Stairs Upper", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS, {[]{return Here(DODONGOS_CAVERN_FAR_BRIDGE, []{return HookshotOrBoomerang;}) || CanUse(LONGSHOT);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || (CanDoGlitch(GlitchType::HammerSlide, GlitchDifficulty::NOVICE) && HookshotOrBoomerang);}}),
|
||||
LocationAccess(DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS, {[]{return IsAdult || CanChildAttack;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_STAIRS_LOWER, {[]{return true;}}),
|
||||
Entrance(DODONGOS_CAVERN_ARMOS_ROOM, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_COMPASS_ROOM] = Area("Dodongos Cavern Compass Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_COMPASS_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_STAIRS_LOWER, {[]{return IsAdult || HasExplosives || GoronBracelet;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_ARMOS_ROOM] = Area("Dodongos Cavern Armos Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_STAIRS_UPPER, {[]{return true;}}),
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_BOMB_FLOWER_PLATFORM_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_2F_SIDE_ROOM, {[]{return Here(DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash;});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return (GlitchBlueFireWall && BlueFire) || (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));});}}),
|
||||
Entrance(DODONGOS_CAVERN_FIRST_SLINGSHOT_ROOM, {[]{return Here(DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return CanBlastOrSmash || GoronBracelet;});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_BOMB_ROOM_LOWER, []{return (GlitchBlueFireWall && BlueFire) || (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));});}}),
|
||||
Entrance(DODONGOS_CAVERN_BOMB_ROOM_UPPER, {[]{return (IsAdult && LogicDCJump) || CanUse(HOVER_BOOTS) || (IsAdult && CanUse(LONGSHOT));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE) ||
|
||||
(IsAdult && (CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(SLINGSHOT)) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED));}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_2F_SIDE_ROOM] = Area("Dodongos Cavern 2F Side Room", "Dodongos Cavern", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_BOMB_ROOM_LOWER, {[]{return true;}}),
|
||||
Entrance(DODONGOS_CAVERN_UPPER_LIZALFOS, {[]{return CanUse(SLINGSHOT) || CanUse(BOW) || LogicDCSlingshotSkip;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || (IsAdult && CanUse(HOOKSHOT) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED));}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_UPPER_LIZALFOS] = Area("Dodongos Cavern Upper Lizalfos", "Dodongos Cavern", 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;});},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
Entrance(DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM, {[]{return Here(DODONGOS_CAVERN_LOWER_LIZALFOS, []{return IsAdult || Slingshot || Sticks || KokiriSword || HasExplosives;});},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_SECOND_SLINGSHOT_ROOM] = Area("Dodongos Cavern Second Slingshot Room", "Dodongos Cavern", 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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || (IsAdult && CanUse(HOOKSHOT) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED));}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_BOMB_ROOM_UPPER] = Area("Dodongos Cavern Bomb Room Upper", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(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;}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_FAR_BRIDGE] = Area("Dodongos Cavern Far Bridge", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_END_OF_BRIDGE_CHEST, {[]{return Here(DODONGOS_CAVERN_FAR_BRIDGE, []{return CanBlastOrSmash;});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_FAR_BRIDGE, []{return (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));}) ||
|
||||
CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_LOBBY, {[]{return true;}}),
|
||||
Entrance(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, {
|
||||
//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;});},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_BOSS_AREA, []{return (GlitchBlueFireWall && BlueFire) || (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED));});}}),
|
||||
Entrance(DODONGOS_CAVERN_BOSS_ROOM, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_BACK_ROOM] = Area("Dodongos Cavern Back Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_GS_BACK_ROOM, {[]{return IsAdult || CanChildAttack;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_BOSS_AREA, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_BOSS_ROOM] = Area("Dodongos Cavern Boss Room", "Dodongos Cavern", DODONGOS_CAVERN, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&DodongosCavernClear, {[]{return DodongosCavernClear || (Here(DODONGOS_CAVERN_BOSS_ROOM, []{return HasExplosives || (CanUse(MEGATON_HAMMER) && CanShield);}) && (Bombs || GoronBracelet) && (IsAdult || Sticks || KokiriSword));},
|
||||
/*Glitched*/[]{return Here(DODONGOS_CAVERN_BOSS_ROOM, []{return HasExplosives || (CanUse(MEGATON_HAMMER) && CanShield) || (GlitchBlueFireWall && BlueFire);}) && (HasExplosives || GoronBracelet) && (IsAdult || Sticks || KokiriSword || CanUse(MEGATON_HAMMER));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_BOSS_ROOM_CHEST, {[]{return true;}}),
|
||||
LocationAccess(DODONGOS_CAVERN_KING_DODONGO_HEART, {[]{return DodongosCavernClear;}}),
|
||||
LocationAccess(KING_DODONGO, {[]{return DodongosCavernClear;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_BOSS_AREA, {[]{return true;}}),
|
||||
Entrance(DODONGOS_CAVERN_ENTRYWAY, {[]{return DodongosCavernClear;}}),
|
||||
});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(DODONGOS_CAVERN_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(DODONGOS_CAVERN_MQ_LOBBY, {[]{return Here(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, {
|
||||
//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;}}),
|
||||
}, {
|
||||
//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);}}),
|
||||
//Trick: IsAdult || HasExplosives || (LogicDCMQChildBombs && (KokiriSword || Sticks) && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
|
||||
Entrance(DODONGOS_CAVERN_MQ_BOSS_AREA, {[]{return HasExplosives;}}),
|
||||
//Trick: HasExplosives || (LogicDCMQEyes && GoronBracelet && (IsAdult || LogicDCMQChildBack) && ((IsChild && CanUse(STICKS)) || CanUse(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(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);}}),
|
||||
});
|
||||
|
||||
areaTable[DODONGOS_CAVERN_MQ_BOMB_BAG_AREA] = Area("Dodongos Cavern MQ Bomb Bag Area", "Dodongos Cavern", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return true;}}),
|
||||
EventAccess(&DodongosCavernClear, {[]{return DodongosCavernClear || (CanBlastOrSmash && (Bombs || GoronBracelet) && (IsAdult || Sticks || KokiriSword));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(DODONGOS_CAVERN_MQ_UNDER_GRAVE_CHEST, {[]{return true;}}),
|
||||
LocationAccess(DODONGOS_CAVERN_BOSS_ROOM_CHEST, {[]{return true;}}),
|
||||
LocationAccess(DODONGOS_CAVERN_KING_DODONGO_HEART, {[]{return CanBlastOrSmash && (Bombs || GoronBracelet) && (IsAdult || Sticks || KokiriSword);}}),
|
||||
LocationAccess(KING_DODONGO, {[]{return CanBlastOrSmash && (Bombs || GoronBracelet) && (IsAdult || Sticks || KokiriSword);}}),
|
||||
LocationAccess(DODONGOS_CAVERN_MQ_GS_BACK_AREA, {[]{return true;}}),
|
||||
}, {});
|
||||
}
|
||||
}
|
@ -0,0 +1,456 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_FireTemple() {
|
||||
/*--------------------------
|
||||
| VANILLA/MQ DECIDER |
|
||||
---------------------------*/
|
||||
areaTable[FIRE_TEMPLE_ENTRYWAY] = Area("Fire Temple Entryway", "Fire Temple", 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;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::FireTemple.IsVanilla()) {
|
||||
areaTable[FIRE_TEMPLE_FIRST_ROOM] = Area("Fire Temple First Room", "Fire Temple", 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);},
|
||||
/*Glitched*/[]{return ((IsAdult && CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::EXPERT)) ||
|
||||
(GlitchFireGrunzClip && Bombs && IsAdult && CanUse(HOVER_BOOTS) && CanSurviveDamage)) && (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;}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_NEAR_BOSS_ROOM] = Area("Fire Temple Near Boss Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return FairyPot || (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_NEAR_BOSS_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}),
|
||||
Entrance(FIRE_TEMPLE_BOSS_ROOM, {[]{return BossKeyFireTemple && ((IsAdult && LogicFireBossDoorJump) || CanUse(HOVER_BOOTS) || Here(FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return CanUse(MEGATON_HAMMER);}));},
|
||||
/*Glitched*/[]{return BossKeyFireTemple && (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) ||
|
||||
(Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)));}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_BOSS_ROOM] = Area("Fire Temple Boss Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FireTempleClear, {[]{return FireTempleClear || (FireTimer >= 64 && CanUse(MEGATON_HAMMER));},
|
||||
/*Glitched*/[]{return FireTimer >= 48 && ((CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) ||
|
||||
CanUse(MEGATON_HAMMER)) && Bombs && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_VOLVAGIA_HEART, {[]{return FireTempleClear;}}),
|
||||
LocationAccess(VOLVAGIA, {[]{return FireTempleClear;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_ENTRYWAY, {[]{return FireTempleClear;}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_LOOP_ENEMIES] = Area("Fire Temple Loop Enemies", "Fire Temple", 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;});},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_LOOP_TILES] = Area("Fire Temple Loop Tiles", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_GS_BOSS_KEY_LOOP, {[]{return IsAdult || CanChildAttack;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_LOOP_ENEMIES, {[]{return true;}}),
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_FLARE_DANCER_CHEST, {[]{return (HasExplosives || CanUse(MEGATON_HAMMER)) && IsAdult;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)) ||
|
||||
(CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED) && HasBombchus && CanShield && (Slingshot || CanUse(BOW) || CanUse(HOOKSHOT)));}}),
|
||||
}, {
|
||||
//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);});}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_LOOP_HAMMER_SWITCH] = Area("Fire Temple Loop Hammer Switch", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FireLoopSwitch, {[]{return FireLoopSwitch || CanUse(MEGATON_HAMMER);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE) && Bombs && CanTakeDamage && CanUse(STICKS);}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_LOOP_FLARE_DANCER, {[]{return true;}}),
|
||||
Entrance(FIRE_TEMPLE_LOOP_GORON_ROOM, {[]{return FireLoopSwitch;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_LOOP_GORON_ROOM] = Area("Fire Temple Loop Goron Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_BOSS_KEY_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_LOOP_HAMMER_SWITCH, {[]{return FireLoopSwitch;}}),
|
||||
Entrance(FIRE_TEMPLE_LOOP_EXIT, {[]{return FireLoopSwitch;}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_LOOP_EXIT] = Area("Fire Temple Loop Exit", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_FIRST_ROOM, {[]{return true;}}),
|
||||
Entrance(FIRE_TEMPLE_LOOP_GORON_ROOM, {[]{return FireLoopSwitch;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_BIG_LAVA_ROOM] = Area("Fire Temple Big Lava Room", "Fire Temple", 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);},
|
||||
/*Glitched*/[]{return FireTimer >= 48 && ((CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)) ||
|
||||
(IsAdult && (SongOfTime && (CanDoGlitch(GlitchType::DungeonBombOI, GlitchDifficulty::INTERMEDIATE) || (CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && (Bugs || Fish) && CanShield)))));}}),
|
||||
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM_SOUTH_GORON, {[]{return IsAdult && HasExplosives;},
|
||||
/*Glitched*/[]{return FireTimer >= 48 && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(FIRE_TEMPLE_FIRE_PILLAR_ROOM, {[]{return SmallKeys(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_BIG_LAVA_ROOM_LOWER_OPEN_DOOR_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM, {[]{return IsAdult;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_BIG_LAVA_ROOM_BLOCKED_DOOR_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_BIG_LAVA_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 3);}}),
|
||||
Entrance(FIRE_TEMPLE_SHORTCUT_ROOM, {[]{return FireTimer >= 56 && SmallKeys(FIRE_TEMPLE, 4);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_SHORTCUT_ROOM] = Area("Fire Temple Shortcut Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_BOULDER_MAZE_SHORTCUT_CHEST, {[]{return Here(FIRE_TEMPLE_SHORTCUT_CLIMB, []{return true;});},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
}, {
|
||||
//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;});},
|
||||
/*Glitched*/[]{return (GoronBracelet || LogicFireStrength) && Bombs && CanSurviveDamage && CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(FIRE_TEMPLE_BOULDER_MAZE_LOWER, {[]{return (GoronBracelet || (IsAdult && LogicFireStrength)) && (HasExplosives || (IsAdult && (CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(SLINGSHOT))));},
|
||||
/*Glitched*/[]{return (GoronBracelet || (IsAdult && LogicFireStrength)) && (CanDoGlitch(GlitchType::SuperStab, GlitchDifficulty::NOVICE) ||
|
||||
(CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanUse(STICKS)));}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_SHORTCUT_CLIMB] = Area("Fire Temple Shortcut Climb", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_SHORTCUT_ROOM, {[]{return true;}}),
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_BOULDER_MAZE_LOWER_CHEST, {[]{return true;}}),
|
||||
LocationAccess(FIRE_TEMPLE_GS_BOULDER_MAZE, {[]{return HasExplosives && (IsAdult || Boomerang || CanUse(HOOKSHOT));},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE) && Bombs) ||
|
||||
Here(FIRE_TEMPLE_BOULDER_MAZE_UPPER, []{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);});}}),
|
||||
}, {
|
||||
//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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE) && Bombs;}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_BOULDER_MAZE_LOWER_SIDE_ROOM] = Area("Fire Temple Boulder Maze Lower Side Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_BOULDER_MAZE_SIDE_ROOM_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {}, {
|
||||
//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);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_FIRE_WALL_CHASE] = Area("Fire Temple Fire Wall Chase", "Fire Temple", 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;},
|
||||
/*Glitched*/[]{return FireTimer >= 32 && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(FIRE_TEMPLE_CORRIDOR, {[]{return FireTimer >= 24 && IsAdult && SmallKeys(FIRE_TEMPLE, 7);},
|
||||
/*Glitched*/[]{return FireTimer >= 32 && SmallKeys(FIRE_TEMPLE, 7) && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && Bombs && HasBombchus && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_MAP_AREA] = Area("Fire Temple Map Area", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_MAP_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(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));}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_SCARECROW_ROOM] = Area("Fire Temple Scarecrow Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_GS_SCARECROW_CLIMB, {[]{return IsAdult || CanChildAttack;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_BOULDER_MAZE_UPPER, {[]{return true;}}),
|
||||
Entrance(FIRE_TEMPLE_EAST_PEAK, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_EAST_PEAK] = Area("Fire Temple East Peak", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_SCARECROW_CHEST, {[]{return true;}}),
|
||||
LocationAccess(FIRE_TEMPLE_GS_SCARECROW_TOP, {[]{return CanUseProjectile;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_SCARECROW_ROOM, {[]{return true;}}),
|
||||
Entrance(FIRE_TEMPLE_EAST_CENTRAL_ROOM, {[]{return CanTakeDamage;}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_CORRIDOR] = Area("Fire Temple Corridor", "Fire Temple", 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;}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_FIRE_MAZE_ROOM] = Area("Fire Temple Fire Maze Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_CORRIDOR, {[]{return true;}}),
|
||||
Entrance(FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return CanUse(HOVER_BOOTS);},
|
||||
/*Glitched*/[]{return Bombs && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE) || (CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::ADVANCED) && Bombs && CanShield);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_FIRE_MAZE_UPPER] = Area("Fire Temple Fire Maze Upper", "Fire Temple", 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);},
|
||||
/*Glitched*/[]{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_FIRE_MAZE_SIDE_ROOM] = Area("Fire Temple Fire Maze Side Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_COMPASS_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_HIGHEST_GORON_CHEST, {[]{return Here(FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return CanPlay(SongOfTime) && CanUse(MEGATON_HAMMER);});},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::INTERMEDIATE) || Here(FIRE_TEMPLE_WEST_CENTRAL_UPPER, []{return (IsAdult || CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) ||
|
||||
(Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE))) &&
|
||||
(((SongOfTime && (((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || CanDoGlitch(GlitchType::DungeonBombOI, GlitchDifficulty::NOVICE))) ||
|
||||
CanPlay(SongOfTime)) && ((CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE)) || CanUse(MEGATON_HAMMER)));});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return SmallKeys(FIRE_TEMPLE, 8);}}),
|
||||
Entrance(FIRE_TEMPLE_WEST_CENTRAL_UPPER, {[]{return IsAdult && CanPlay(SongOfTime);},
|
||||
/*Glitched*/[]{return (IsAdult && SongOfTime && (((Bugs || Fish) && CanShield && (CanSurviveDamage || (CanTakeDamage && NumBottles >= 2)) && Bombs && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
(CanDoGlitch(GlitchType::DungeonBombOI, GlitchDifficulty::NOVICE)))) || (Bombs && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
Entrance(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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_BOSS_ROOM, {[]{return false;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(FIRE_TEMPLE_FIRE_MAZE_UPPER, {[]{return true;}}),
|
||||
Entrance(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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_FIRE_MAZE_ROOM, {[]{return false;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) || (Bombs && CanShield && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::ADVANCED));}}),
|
||||
Entrance(FIRE_TEMPLE_WEST_CENTRAL_LOWER, {[]{return true;}}),
|
||||
Entrance(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, {}, {}, {
|
||||
//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);});}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_WEST_CLIMB] = Area("Fire Temple West Climb", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_UPPER_FLARE_DANCER, {[]{return true;}}),
|
||||
Entrance(FIRE_TEMPLE_WEST_PEAK, {[]{return CanUseProjectile;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::SuperStab, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_WEST_PEAK] = Area("Fire Temple West Peak", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(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);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_HAMMER_RETURN_PATH] = Area("Fire Temple Hammer Return Path", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_ABOVE_FIRE_MAZE, {[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_ABOVE_FIRE_MAZE] = Area("Fire Temple Above Fire Maze", "Fire Temple", 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);}}),
|
||||
});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {}, {
|
||||
//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 && FireTimer >= 24
|
||||
&& (CanUse(HOVER_BOOTS) || 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)))))
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(FIRE_TEMPLE_MQ_BOSS_ROOM, {[]{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);}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_MQ_LOWER_LOCKED_DOOR] = Area("Fire Temple MQ Lower Locked Door", "Fire Temple", 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);}}),
|
||||
}, {});
|
||||
|
||||
areaTable[FIRE_TEMPLE_MQ_BIG_LAVA_ROOM] = Area("Fire Temple MQ Big Lava Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return FairyPot || (HasFireSource && Bow && IsAdult && (CanUse(HOOKSHOT) || LogicFireSongOfTime));}}),
|
||||
//Trick: HasFireSource && (Bow || LogicFireMQBKChest) && IsAdult && (CanUse(HOOKSHOT) || LogicFireSongOfTime)
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return HasFireSource && Bow && 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);}}),
|
||||
//Trick: HasFireSource && HasExplosives && IsAdult && (CanUse(HOOKSHOT) || LogicFireMQBlockedChest)
|
||||
LocationAccess(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;}}),
|
||||
//Trick: IsAdult && CanUse(GORON_TUNIC) && SmallKeys(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_MQ_LIZALFOS_MAZE_LOWER_CHEST, {[]{return true;}}),
|
||||
LocationAccess(FIRE_TEMPLE_MQ_LIZALFOS_MAZE_SIDE_ROOM_CHEST, {[]{return HasExplosives && HasAccessTo(FIRE_TEMPLE_MQ_UPPER_MAZE);}}),
|
||||
//Trick: HasExplosives && (LogicFireMQMazeSideRoom || FIRE_TEMPLE_MQ_UPPER_MAZE.Adult())
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_MQ_UPPER_MAZE, {[]{return HasExplosives && IsAdult && CanUse(HOOKSHOT);}}),
|
||||
//Trick: (IsAdult && ((HasExplosives && CanUse(HOOKSHOT)) || (LogicFireMQMazeHovers && CanUse(HOVER_BOOTS)))) || LogicFireMQMazeJump
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_MQ_UPPER_MAZE] = Area("Fire Temple MQ Upper Maze", "Fire Temple", 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);}}),
|
||||
}, {
|
||||
//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));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FIRE_TEMPLE_MQ_UPPER, {[]{return SmallKeys(FIRE_TEMPLE, 3) && IsAdult && ((CanUse(BOW) && CanUse(HOOKSHOT)) || CanUse(FIRE_ARROWS));}}),
|
||||
});
|
||||
|
||||
areaTable[FIRE_TEMPLE_MQ_UPPER] = Area("Fire Temple MQ Upper", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_MQ_FREESTANDING_KEY, {[]{return IsAdult && CanUse(HOOKSHOT);}}),
|
||||
//Trick: (IsAdult && CanUse(HOOKSHOT)) || LogicFireMQFlameMaze
|
||||
LocationAccess(FIRE_TEMPLE_MQ_CHEST_ON_FIRE, {[]{return IsAdult && CanUse(HOOKSHOT) && 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;}}),
|
||||
//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);}}),
|
||||
//Trick: (IsAdult && CanUse(HOOKSHOT) && SmallKeys(FIRE_TEMPLE, 5)) || (LogicFireMQAboveMazeGS && IsAdult && CanUse(LONGSHOT))
|
||||
}, {});
|
||||
|
||||
areaTable[FIRE_TEMPLE_MQ_BOSS_ROOM] = Area("Fire Temple MQ Boss Room", "Fire Temple", FIRE_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FireTempleClear, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FIRE_TEMPLE_VOLVAGIA_HEART, {[]{return true;}}),
|
||||
LocationAccess(VOLVAGIA, {[]{return true;}}),
|
||||
}, {});
|
||||
}
|
||||
}
|
@ -0,0 +1,452 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_ForestTemple() {
|
||||
/*--------------------------
|
||||
| VANILLA/MQ DECIDER |
|
||||
---------------------------*/
|
||||
areaTable[FOREST_TEMPLE_ENTRYWAY] = Area("Forest Temple Entryway", "Forest Temple", 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;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::ForestTemple.IsVanilla()) {
|
||||
areaTable[FOREST_TEMPLE_FIRST_ROOM] = Area("Forest Temple First Room", "Forest Temple", 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);},
|
||||
/*Glitched*/[]{return (Bombs && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::SuperStab, GlitchDifficulty::NOVICE);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(FOREST_TEMPLE_SOUTH_CORRIDOR, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_SOUTH_CORRIDOR] = Area("Forest Temple South Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_FIRST_ROOM, {[]{return true;}}),
|
||||
Entrance(FOREST_TEMPLE_LOBBY, {[]{return IsAdult || CanChildAttack || Nuts;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_LOBBY] = Area("Forest Temple Lobby", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ForestTempleMeg, {[]{return ForestTempleMeg || (ForestTempleJoelle && ForestTempleBeth && ForestTempleAmy && CanUse(BOW));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_GS_LOBBY, {[]{return HookshotOrBoomerang;},
|
||||
/*Glitched*/[]{return IsAdult && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE);}}),
|
||||
}, {
|
||||
//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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::NOVICE) || (SongOfTime && (CanDoGlitch(GlitchType::DungeonBombOI, GlitchDifficulty::INTERMEDIATE) ||
|
||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))));}}),
|
||||
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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE);}}),
|
||||
Entrance(FOREST_TEMPLE_BOSS_REGION, {[]{return ForestTempleMeg;}}),
|
||||
Entrance(FOREST_TEMPLE_BOSS_ROOM, {[]{return false;},
|
||||
/*Glitched*/[]{return IsAdult && (CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT)) && GlitchForestBKSkip;}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_NORTH_CORRIDOR] = Area("Forest Temple North Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_LOBBY, {[]{return true;}}),
|
||||
Entrance(FOREST_TEMPLE_LOWER_STALFOS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_LOWER_STALFOS] = Area("Forest Temple Lower Stalfos", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_FIRST_STALFOS_CHEST, {[]{return IsAdult || KokiriSword;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {
|
||||
//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);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD, {[]{return CanUse(LONGSHOT) || Here(FOREST_TEMPLE_NW_OUTDOORS_UPPER, []{return HookshotOrBoomerang;});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_LOBBY, {[]{return CanPlay(SongOfTime);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::NOVICE) || (SongOfTime && (CanDoGlitch(GlitchType::DungeonBombOI, GlitchDifficulty::INTERMEDIATE) ||
|
||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))));}}),
|
||||
Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return false;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE) || (IsAdult && CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::NOVICE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
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_ROOM, {[]{return false;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_NW_OUTDOORS_UPPER] = Area("Forest Temple NW Outdoors Upper", "Forest Temple", 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));},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
}, {}, {
|
||||
//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;}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_NE_OUTDOORS_LOWER] = Area("Forest Temple NE Outdoors Lower", "Forest Temple", 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));},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_RAISED_ISLAND_COURTYARD_CHEST, {[]{return CanUse(HOOKSHOT) || HasAccessTo(FOREST_TEMPLE_FALLING_ROOM);}}),
|
||||
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;});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_LOBBY, {[]{return true;}}),
|
||||
Entrance(FOREST_TEMPLE_NE_OUTDOORS_UPPER, {[]{return CanUse(LONGSHOT);}}),
|
||||
Entrance(FOREST_TEMPLE_SEWER, {[]{return GoldScale || CanUse(IRON_BOOTS) || HasAccessTo(FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}),
|
||||
Entrance(FOREST_TEMPLE_FALLING_ROOM, {[]{return false;},
|
||||
/*Glitched*/[]{return Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_NE_OUTDOORS_UPPER] = Area("Forest Temple NE Outdoors Upper", "Forest Temple", 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));},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
}, {}, {
|
||||
//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);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::EXPERT);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_MAP_ROOM] = Area("Forest Temple Map Room", "Forest Temple", 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));});}}),
|
||||
}, {
|
||||
//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));});}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_SEWER] = Area("Forest Temple Sewer", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_WELL_CHEST, {[]{return HasAccessTo(FOREST_TEMPLE_NE_OUTDOORS_UPPER);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_NW_OUTDOORS_LOWER, {[]{return true;}}),
|
||||
Entrance(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, {}, {}, {
|
||||
//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));});}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_FLOORMASTER_ROOM] = Area("Forest Temple Floormaster Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_FLOORMASTER_CHEST, {[]{return IsAdult || CanChildDamage;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_LOBBY, {[]{return SmallKeys(FOREST_TEMPLE, 1, 5);}}),
|
||||
Entrance(FOREST_TEMPLE_BLOCK_PUSH_ROOM, {[]{return IsAdult || CanChildAttack || Nuts;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_BLOCK_PUSH_ROOM] = Area("Forest Temple Block Push Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_EYE_SWITCH_CHEST, {[]{return GoronBracelet && (CanUse(BOW) || CanUse(SLINGSHOT));},
|
||||
/*Glitched*/[]{return IsAdult && (CanUse(BOW) || CanUse(SLINGSHOT)) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_WEST_CORRIDOR, {[]{return true;}}),
|
||||
Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return CanUse(HOVER_BOOTS) || (LogicForestOutsideBackdoor && IsAdult && GoronBracelet);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) || (Bombs && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
Entrance(FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return IsAdult && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);},
|
||||
/*Glitched*/[]{return ((IsAdult && (Bow || Hookshot || CanUse(SLINGSHOT)) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)) ||
|
||||
(Bombs && GoronBracelet && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE))) && SmallKeys(FOREST_TEMPLE, 2);}}),
|
||||
Entrance(FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return CanUse(BOW) && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);},
|
||||
/*Glitched*/[]{return ((IsAdult && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)) ||
|
||||
(IsChild && Bombs && GoronBracelet && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE))) && (CanUse(BOW) || CanUse(SLINGSHOT)) && SmallKeys(FOREST_TEMPLE, 2);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_NW_CORRIDOR_TWISTED] = Area("Forest Temple NW Corridor Twisted", "Forest Temple", 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);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED] = Area("Forest Temple NW Corridor Straightened", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(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);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_RED_POE_ROOM] = Area("Forest Temple Red Poe Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ForestTempleJoelle, {[]{return ForestTempleJoelle || CanUse(BOW);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(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;}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_UPPER_STALFOS] = Area("Forest Temple Upper Stalfos", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_BOW_CHEST, {[]{return IsAdult || KokiriSword;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_RED_POE_ROOM, {[]{return IsAdult || KokiriSword;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
Entrance(FOREST_TEMPLE_BLUE_POE_ROOM, {[]{return IsAdult || KokiriSword;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_BLUE_POE_ROOM] = Area("Forest Temple Blue Poe Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ForestTempleBeth, {[]{return ForestTempleBeth || CanUse(BOW);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(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);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_NE_CORRIDOR_STRAIGHTENED] = Area("Forest Temple NE Corridor Straightened", "Forest Temple", 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);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_NE_CORRIDOR_TWISTED] = Area("Forest Temple NE Corridor Twisted", "Forest Temple", 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;}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_FROZEN_EYE_ROOM] = Area("Forest Temple Frozen Eye Room", "Forest Temple", 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));}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_FALLING_ROOM] = Area("Forest Temple Falling Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(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;}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_GREEN_POE_ROOM] = Area("Forest Temple Green Poe Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ForestTempleAmy, {[]{return ForestTempleAmy || CanUse(BOW);}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_FALLING_ROOM, {[]{return true;}}),
|
||||
Entrance(FOREST_TEMPLE_EAST_CORRIDOR, {[]{return ForestTempleAmy;}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_EAST_CORRIDOR] = Area("Forest Temple East Corridor", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_LOBBY, {[]{return IsAdult || CanChildAttack || Nuts;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
Entrance(FOREST_TEMPLE_GREEN_POE_ROOM, {[]{return IsAdult || CanChildAttack || Nuts;},
|
||||
/*Glitched*/[]{return CanUse(MEGATON_HAMMER);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_BOSS_REGION] = Area("Forest Temple Boss Region", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_BASEMENT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(FOREST_TEMPLE_GS_BASEMENT, {[]{return HookshotOrBoomerang;},
|
||||
/*Glitched*/[]{return Bombs && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_LOBBY, {[]{return true;}}),
|
||||
Entrance(FOREST_TEMPLE_BOSS_ROOM, {[]{return BossKeyForestTemple;}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_BOSS_ROOM] = Area("Forest Temple Boss Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ForestTempleClear, {[]{return ForestTempleClear || ((IsAdult || KokiriSword) && (CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT)));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_PHANTOM_GANON_HEART, {[]{return ForestTempleClear;}}),
|
||||
LocationAccess(PHANTOM_GANON, {[]{return ForestTempleClear;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_ENTRYWAY, {[]{return ForestTempleClear;}}),
|
||||
});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {}, {
|
||||
//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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(FOREST_TEMPLE_MQ_CENTRAL_AREA, {[]{return SmallKeys(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, {
|
||||
//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;}}),
|
||||
}, {
|
||||
//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;}}),
|
||||
//Trick: IsAdult && (GoronBracelet || (LogicForestMQBlockPuzzle && HasBombchus && IsAdult && CanUse(HOOKSHOT)))
|
||||
Entrance(FOREST_TEMPLE_MQ_OUTDOOR_LEDGE, {[]{return false;}}),
|
||||
//Trick: (LogicForestMQHallwaySwitchJumpslash && IsAdult && CanUse(HOVER_BOOTS)) || (LogicForestMQHallwaySwitchHookshot && IsAdult && CanUse(HOOKSHOT))
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_MQ_BOSS_KEY_CHEST, {[]{return SmallKeys(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);}}),
|
||||
//Trick: SmallKeys(FOREST_TEMPLE, 3) || (LogicForestMQHallwaySwitchJumpslash && ((IsAdult && CanUse(HOOKSHOT)) || LogicForestOutsideBackdoor))
|
||||
Entrance(FOREST_TEMPLE_MQ_NW_OUTDOORS, {[]{return SmallKeys(FOREST_TEMPLE, 2);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_MQ_OUTDOOR_LEDGE] = Area("Forest Temple MQ Outdoor Ledge", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_MQ_REDEAD_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_MQ_NE_OUTDOORS, {[]{return (IsAdult && (CanUse(IRON_BOOTS) || CanUse(LONGSHOT))) || 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);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_MQ_NE_OUTDOORS] = Area("Forest Temple MQ NE Outdoors", "Forest Temple", 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));}}),
|
||||
}, {
|
||||
//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));}}),
|
||||
}, {
|
||||
//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);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_MQ_OUTDOORS_TOP_LEDGES] = Area("Forest Temple MQ Outdoors Top Ledges", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(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 false;}}),
|
||||
//Trick: LogicForestOutdoorsLedge && IsAdult && CanUse(HOVER_BOOTS)
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_MQ_NE_OUTDOORS_LEDGE] = Area("Forest Temple MQ NE Outdoors Ledge", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(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);}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_MQ_BOW_REGION] = Area("Forest Temple MQ Bow Region", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ForestTempleJoAndBeth, {[]{return ForestTempleJoAndBeth || (IsAdult && CanUse(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);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(FOREST_TEMPLE_MQ_FALLING_ROOM, {[]{return SmallKeys(FOREST_TEMPLE, 5) && ((IsAdult && CanUse(BOW)) || CanUse(DINS_FIRE));}}),
|
||||
});
|
||||
|
||||
areaTable[FOREST_TEMPLE_MQ_FALLING_ROOM] = Area("Forest Temple MQ Falling Room", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ForestTempleAmyAndMeg, {[]{return ForestTempleAmyAndMeg || (IsAdult && CanUse(BOW) && SmallKeys(FOREST_TEMPLE, 6));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_MQ_FALLING_CEILING_ROOM_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {
|
||||
//Events
|
||||
EventAccess(&ForestTempleClear, {[]{return ForestTempleClear || BossKeyForestTemple;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(FOREST_TEMPLE_MQ_BASEMENT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(FOREST_TEMPLE_PHANTOM_GANON_HEART, {[]{return BossKeyForestTemple;}}),
|
||||
LocationAccess(PHANTOM_GANON, {[]{return BossKeyForestTemple;}}),
|
||||
}, {});
|
||||
}
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
#include "../trial.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(GANONS_CASTLE_LOBBY, {[]{return Dungeon::GanonsCastle.IsVanilla();}}),
|
||||
Entrance(GANONS_CASTLE_MQ_LOBBY, {[]{return Dungeon::GanonsCastle.IsMQ();}}),
|
||||
Entrance(GANONS_CASTLE_GROUNDS, {[]{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, {}, {}, {
|
||||
//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()) &&
|
||||
(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);}}),
|
||||
});
|
||||
|
||||
areaTable[GANONS_CASTLE_DEKU_SCRUBS] = Area("Ganon's Castle Deku Scrubs", "Ganon's Castle", 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;}}),
|
||||
}, {});
|
||||
|
||||
areaTable[GANONS_CASTLE_FOREST_TRIAL] = Area("Ganon's Castle Forest Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ForestTrialClear, {[]{return CanUse(LIGHT_ARROWS) && (FireArrows || DinsFire);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(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, {
|
||||
//Events
|
||||
EventAccess(&FireTrialClear, {[]{return CanUse(GORON_TUNIC) && CanUse(GOLDEN_GAUNTLETS) && CanUse(LIGHT_ARROWS) && CanUse(LONGSHOT);}}),
|
||||
}, {}, {});
|
||||
|
||||
areaTable[GANONS_CASTLE_WATER_TRIAL] = Area("Ganon's Castle Water Trial", "Ganon's Castle", 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);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(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, {
|
||||
//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))))));}}),
|
||||
}, {
|
||||
//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)));}}),
|
||||
}, {});
|
||||
|
||||
areaTable[GANONS_CASTLE_SPIRIT_TRIAL] = Area("Ganon's Castle Spirit Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&NutPot, {[]{return NutPot || ((LogicSpiritTrialHookshot || CanUse(HOOKSHOT)) && HasBombchus && Bow && MirrorShield && IsAdult);}}),
|
||||
EventAccess(&SpiritTrialClear, {[]{return CanUse(LIGHT_ARROWS) && MirrorShield && HasBombchus && (LogicSpiritTrialHookshot || CanUse(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));}}),
|
||||
}, {});
|
||||
|
||||
areaTable[GANONS_CASTLE_LIGHT_TRIAL] = Area("Ganon's Castle Light Trial", "Ganon's Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&LightTrialClear, {[]{return CanUse(LIGHT_ARROWS) && CanUse(HOOKSHOT) && SmallKeys(GANONS_CASTLE, 2) && (LogicLensCastle || CanUse(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);}}),
|
||||
}, {});
|
||||
}
|
||||
|
||||
areaTable[GANONS_CASTLE_TOWER] = Area("Ganon's Castle Tower", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(GANONS_TOWER_BOSS_KEY_CHEST, {[]{return true;}}),
|
||||
LocationAccess(GANONDORF_HINT, {[]{return BossKeyGanonsCastle;}}),
|
||||
LocationAccess(GANON, {[]{return BossKeyGanonsCastle && CanUse(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, {}, {}, {
|
||||
//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()) &&
|
||||
(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);}}),
|
||||
});
|
||||
|
||||
areaTable[GANONS_CASTLE_MQ_DEKU_SCRUBS] = Area("Ganon's Castle MQ Deku Scrubs", "Ganon's Castle", 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;}}),
|
||||
}, {});
|
||||
|
||||
areaTable[GANONS_CASTLE_MQ_FOREST_TRIAL] = Area("Ganon's Castle MQ Forest Trial", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ForestTrialClear, {[]{return IsAdult && CanUse(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;}}),
|
||||
}, {});
|
||||
|
||||
areaTable[GANONS_CASTLE_MQ_FIRE_TRIAL] = Area("Ganon's Castle MQ Fire Trial", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FireTrialClear, {[]{return CanUse(GORON_TUNIC) && CanUse(GOLDEN_GAUNTLETS) && CanUse(LIGHT_ARROWS) && (CanUse(LONGSHOT) || CanUse(HOVER_BOOTS));}}),
|
||||
//Trick: CanUse(GORON_TUNIC) && CanUse(GOLDEN_GAUNTLETS) && CanUse(LIGHT_ARROWS) && (CanUse(LONGSHOT) || HoverBoots || (LogicFireTrialMQ && CanUse(HOOKSHOT)))
|
||||
}, {}, {});
|
||||
|
||||
areaTable[GANONS_CASTLE_MQ_WATER_TRIAL] = Area("Ganon's Castle MQ Water Trial", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&WaterTrialClear, {[]{return BlueFire && IsAdult && CanUse(LIGHT_ARROWS) && SmallKeys(GANONS_CASTLE, 3);}}),
|
||||
EventAccess(&BlueFireAccess, {[]{return BlueFireAccess || HasBottle;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GANONS_CASTLE_MQ_WATER_TRIAL_CHEST, {[]{return BlueFire && (IsAdult || CanUse(STICKS) || KokiriSword || CanUseProjectile);}}),
|
||||
}, {});
|
||||
|
||||
areaTable[GANONS_CASTLE_MQ_SHADOW_TRIAL] = Area("Ganon's Castle MQ Shadow Trial", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ShadowTrialClear, {[]{return IsAdult && CanUse(LIGHT_ARROWS) && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH)) && (CanUse(HOVER_BOOTS) || (CanUse(HOOKSHOT) && HasFireSource));}}),
|
||||
//Trick: IsAdult && CanUse(LIGHT_ARROWS) && (LogicLensCastleMQ || CanUse(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)) && (CanUse(HOVER_BOOTS) || (CanUse(HOOKSHOT) && HasFireSource));}}),
|
||||
//Trick: IsAdult && Bow && (LogicLensCastleMQ || CanUse(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, {
|
||||
//Events
|
||||
EventAccess(&SpiritTrialClear, {[]{return IsAdult && CanUse(LIGHT_ARROWS) && Hammer && HasBombchus && FireArrows && MirrorShield;}}),
|
||||
EventAccess(&NutPot, {[]{return NutPot || (Hammer && HasBombchus && IsAdult && CanUse(FIRE_ARROWS) && MirrorShield);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_FIRST_CHEST, {[]{return IsAdult && Bow && Hammer;}}),
|
||||
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_INVISIBLE_CHEST, {[]{return IsAdult && Bow && 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);}}),
|
||||
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_LEFT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && CanUse(FIRE_ARROWS) && CanUse(MIRROR_SHIELD);}}),
|
||||
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_GOLDEN_GAUNTLETS_CHEST, {[]{return IsAdult && Hammer && HasBombchus && CanUse(FIRE_ARROWS) && CanUse(MIRROR_SHIELD);}}),
|
||||
LocationAccess(GANONS_CASTLE_MQ_SPIRIT_TRIAL_SUN_BACK_RIGHT_CHEST, {[]{return IsAdult && Hammer && HasBombchus && CanUse(FIRE_ARROWS) && CanUse(MIRROR_SHIELD);}}),
|
||||
}, {});
|
||||
|
||||
areaTable[GANONS_CASTLE_MQ_LIGHT_TRIAL] = Area("Ganon's Castle MQ Light Trial", "Ganons Castle", GANONS_CASTLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&LightTrialClear, {[]{return IsAdult && CanUse(LIGHT_ARROWS) && SmallKeys(GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH)) && CanUse(HOOKSHOT);}}),
|
||||
//Trick: IsAdult && CanUse(LIGHT_ARROWS) && SmallKeys(GANONS_CASTLE, 3) && (LogicLensCastleMQ || CanUse(LENS_OF_TRUTH)) && (Hookshot || LogicLightTrialMQ)
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GANONS_CASTLE_MQ_LIGHT_TRIAL_LULLABY_CHEST, {[]{return CanPlay(ZeldasLullaby);}}),
|
||||
}, {});
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
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, {}, {}, {
|
||||
//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;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| 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, {}, {
|
||||
//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);}}),
|
||||
}, {
|
||||
//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;}}),
|
||||
});
|
||||
|
||||
areaTable[GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE] = Area("Gerudo Training Grounds Central Maze", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_HIDDEN_CEILING_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 3) && (LogicLensGtg || CanUse(LENS_OF_TRUTH));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE) && (LogicLensGtg || CanUse(LENS_OF_TRUTH));}}),
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_MAZE_PATH_FIRST_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 4);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);}}),
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_MAZE_PATH_SECOND_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 6);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);}}),
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_MAZE_PATH_THIRD_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 7);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);}}),
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_MAZE_PATH_FINAL_CHEST, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 9);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT, {[]{return SmallKeys(GERUDO_TRAINING_GROUNDS, 9);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
|
||||
areaTable[GERUDO_TRAINING_GROUNDS_CENTRAL_MAZE_RIGHT] = Area("Gerudo Training Grounds Central Maze Right", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GERUDO_TRAINING_GROUNDS_HAMMER_ROOM, {[]{return CanUse(HOOKSHOT);}}),
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_UNDERWATER_SILVER_RUPEE_CHEST, {[]{return CanUse(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));}}),
|
||||
});
|
||||
|
||||
areaTable[GERUDO_TRAINING_GROUNDS_HAMMER_ROOM] = Area("Gerudo Training Grounds Hammer Room", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, 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);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GERUDO_TRAINING_GROUNDS_EYE_STATUE_LOWER, {[]{return CanUse(MEGATON_HAMMER) && Bow;}}),
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_EYE_STATUE_CHEST, {[]{return CanUse(BOW);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_NEAR_SCARECROW_CHEST, {[]{return CanUse(BOW);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_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);}}),
|
||||
});
|
||||
|
||||
areaTable[GERUDO_TRAINING_GROUNDS_LIKE_LIKE_ROOM] = Area("Gerudo Training Grounds Like Like Room", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, 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;}}),
|
||||
}, {});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {}, {
|
||||
//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);}}),
|
||||
}, {
|
||||
//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));});}}),
|
||||
});
|
||||
|
||||
areaTable[GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE] = Area("Gerudo Training Grounds MQ Right Side", "Gerudo Training Grounds", GERUDO_TRAINING_GROUNDS, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
//EventAccess(&WallFairy, {[]{return WallFairy || (IsAdult && CanUse(BOW));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_DINOLFOS_CHEST, {[]{return IsAdult;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER, {[]{return (Bow || CanUse(LONGSHOT)) && CanUse(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_UNDERWATER_SILVER_RUPEE_CHEST, {[]{return HasFireSource && IsAdult && CanUse(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(GERUDO_TRAINING_GROUNDS_MQ_FIRST_IRON_KNUCKLE_CHEST, {[]{return IsAdult || KokiriSword || HasExplosives;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GERUDO_TRAINING_GROUNDS_MQ_STALFOS_ROOM, {[]{return IsAdult && CanUse(LONGSHOT);}}),
|
||||
//Trick: (IsAdult && CanUse(LONGSHOT)) || LogicGtgMQWithoutHookshot || (LogicGtgMQWithHookshot && IsAdult && CanUse(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, {
|
||||
//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);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GERUDO_TRAINING_GROUNDS_MQ_BACK_AREAS, {[]{return IsAdult && (LogicLensGtgMQ || CanUse(LENS_OF_TRUTH)) && BlueFire && CanPlay(SongOfTime);}}),
|
||||
//Trick: IsAdult && (LogicLensGtgMQ || CanUse(LENS_OF_TRUTH)) && BlueFire && (CanPlay(SongOfTime) || (LogicGtgFakeWall && IsAdult && CanUse(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, {}, {
|
||||
//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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GERUDO_TRAINING_GROUNDS_MQ_CENTRAL_MAZE_RIGHT, {[]{return Hammer;}}),
|
||||
Entrance(GERUDO_TRAINING_GROUNDS_MQ_RIGHT_SIDE, {[]{return CanUse(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, {}, {
|
||||
//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);}}),
|
||||
}, {
|
||||
//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);}}),
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,234 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_GerudoValley() {
|
||||
areaTable[GERUDO_VALLEY] = Area("Gerudo Valley", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&BugRock, {[]{return BugRock || IsChild;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GV_GS_SMALL_BRIDGE, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;},
|
||||
/*Glitched*/[]{return IsChild && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && 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));},
|
||||
/*Glitched*/[]{return (HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE)) || (IsChild && CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::HERO)) || (IsAdult && (CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HammerSlide, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED) ||
|
||||
(CanUse(HOVER_BOOTS) && (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE) || (CanSurviveDamage && (Bombs || HasBombchus) && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::NOVICE)) || (Bombs && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::ADVANCED))))));}}),
|
||||
});
|
||||
|
||||
areaTable[GV_UPPER_STREAM] = Area("GV Upper Stream", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairy;}}),
|
||||
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(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);},
|
||||
/*Glitched*/[]{return IsChild && EponasSong && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)));}}),
|
||||
LocationAccess(GV_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GV_LOWER_STREAM, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GV_LOWER_STREAM] = Area("GV Lower Stream", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(LAKE_HYLIA, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GV_GROTTO_LEDGE] = Area("GV Grotto Ledge", "Gerudo Valley", 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);}}),
|
||||
});
|
||||
|
||||
areaTable[GV_CRATE_LEDGE] = Area("GV Crate Ledge", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(GV_CRATE_FREESTANDING_POH, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GV_LOWER_STREAM, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GV_FORTRESS_SIDE] = Area("GV Fortress Side", "Gerudo Valley", GERUDO_VALLEY, DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&BrokenSwordAccess, {[]{return IsAdult && (PoachersSawAccess || PoachersSaw);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GV_CHEST, {[]{return IsAdult && (CanUse(MEGATON_HAMMER) || LogicGVHammerChest);},
|
||||
/*Glitched*/[]{return IsAdult && (CanDoGlitch(GlitchType::LedgeCancel, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || (CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE) && (CanTakeDamageTwice || CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED))));}}),
|
||||
LocationAccess(GV_TRADE_SAW, {[]{return IsAdult && PoachersSaw;}}),
|
||||
LocationAccess(GV_GS_BEHIND_TENT, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && IsAdult && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(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;},
|
||||
/*Glitched*/[]{return (HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HammerSlide, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED) ||
|
||||
(CanUse(HOVER_BOOTS) && (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE) || (CanSurviveDamage && (Bombs || HasBombchus) && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::NOVICE)) || (Bombs && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::ADVANCED))));}}),
|
||||
Entrance(GV_CARPENTER_TENT, {[]{return IsAdult;},
|
||||
/*Glitched*/[]{return GlitchGVTentAsChild.Value<bool>();}}),
|
||||
Entrance(GV_STORMS_GROTTO, {[]{return IsAdult && CanOpenStormGrotto;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsAdult && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
||||
});
|
||||
|
||||
areaTable[GV_CARPENTER_TENT] = Area("GV Carpenter Tent", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(GV_FORTRESS_SIDE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GV_OCTOROK_GROTTO] = Area("GV Octorok Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(GV_GROTTO_LEDGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GV_STORMS_GROTTO] = Area("GV Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(GV_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(GV_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GV_FORTRESS_SIDE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GERUDO_FORTRESS] = Area("Gerudo Fortress", "Gerudo Fortress", 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);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE))) && (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen);}}),
|
||||
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);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE);}}),
|
||||
LocationAccess(GF_NORTH_F2_CARPENTER, {[]{return (IsAdult || KokiriSword || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)) && (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) && (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen);}}),
|
||||
LocationAccess(GF_SOUTH_F1_CARPENTER, {[]{return IsAdult || KokiriSword || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE);}}),
|
||||
LocationAccess(GF_SOUTH_F2_CARPENTER, {[]{return IsAdult || KokiriSword || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE);}}),
|
||||
LocationAccess(GF_GERUDO_MEMBERSHIP_CARD, {[]{return CanFinishGerudoFortress;}}),
|
||||
LocationAccess(GF_GS_ARCHERY_RANGE, {[]{return IsAdult && HookshotOrBoomerang && GerudoToken && AtNight && CanGetNightTimeGS;},
|
||||
/*Glitched*/[]{return IsAdult && HookshotOrBoomerang && GlitchGFGuardSneak && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(GF_GS_TOP_FLOOR, {[]{return IsAdult && AtNight && (GerudoToken || CanUse(BOW) || CanUse(HOOKSHOT) || CanUse(HOVER_BOOTS) || LogicGerudoKitchen) && CanGetNightTimeGS;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GV_FORTRESS_SIDE, {[]{return true;}}),
|
||||
Entrance(GF_OUTSIDE_GATE, {[]{return GF_GateOpen;},
|
||||
/*Glitched*/[]{return (IsChild && CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::ADVANCED)) || ((IsChild || ((CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(BOOMERANG)) && GlitchGFGuardSneak)) && ((CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::NOVICE)) ||
|
||||
CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::INTERMEDIATE)) && (CanUse(STICKS) || (BiggoronSword && IsAdult) || CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)));}}),
|
||||
Entrance(GERUDO_TRAINING_GROUNDS_ENTRYWAY, {[]{return GtG_GateOpen && (IsAdult || ShuffleDungeonEntrances);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::INTERMEDIATE) && (HoverBoots || CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::ADVANCED))) || ((IsChild || ((CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(BOOMERANG)) && GlitchGFGuardSneak)) && ((CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) &&
|
||||
CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::INTERMEDIATE)) && (CanUse(STICKS) || (BiggoronSword && IsAdult) || CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)));}}),
|
||||
Entrance(GF_STORMS_GROTTO, {[]{return IsAdult && CanOpenStormGrotto;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsAdult && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
||||
});
|
||||
|
||||
areaTable[GF_OUTSIDE_GATE] = Area("GF Outside Gate", "Gerudo Fortress", 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;}}),
|
||||
});
|
||||
|
||||
areaTable[GF_STORMS_GROTTO] = Area("GF Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(GERUDO_FORTRESS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[WASTELAND_NEAR_FORTRESS] = Area("Wasteland Near Fortress", "Haunted Wasteland", HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(GF_OUTSIDE_GATE, {[]{return true;}}),
|
||||
Entrance(HAUNTED_WASTELAND, {[]{return CanUse(HOVER_BOOTS) || CanUse(LONGSHOT);},
|
||||
/*Glitched*/[]{return ((Bombs || HasBombchus) && CanSurviveDamage && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::NOVICE)) || (CanUse(MEGATON_HAMMER) && CanShield && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::INTERMEDIATE)) ||
|
||||
(Bombs && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::ADVANCED)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)) || GlitchItemlessWasteland;}}),
|
||||
});
|
||||
|
||||
areaTable[HAUNTED_WASTELAND] = Area("Haunted Wasteland", "Haunted Wasteland", HAUNTED_WASTELAND, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return true;}}),
|
||||
EventAccess(&NutPot, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(WASTELAND_CHEST, {[]{return HasFireSource;},
|
||||
/*Glitched*/[]{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
LocationAccess(WASTELAND_BOMBCHU_SALESMAN, {[]{return AdultsWallet && (IsAdult || Sticks || KokiriSword);},
|
||||
/*Glitched*/[]{return AdultsWallet && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE);}}),
|
||||
LocationAccess(WASTELAND_GS, {[]{return HookshotOrBoomerang;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WASTELAND_NEAR_COLOSSUS, {[]{return LogicLensWasteland || CanUse(LENS_OF_TRUTH);}}),
|
||||
Entrance(WASTELAND_NEAR_FORTRESS, {[]{return CanUse(HOVER_BOOTS) || CanUse(LONGSHOT);},
|
||||
/*Glitched*/[]{return ((Bombs || HasBombchus) && CanSurviveDamage && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::NOVICE)) || (CanUse(MEGATON_HAMMER) && CanShield && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::INTERMEDIATE)) ||
|
||||
(Bombs && CanDoGlitch(GlitchType::SuperSlide, GlitchDifficulty::ADVANCED)) || (HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) || GlitchItemlessWasteland;}}),
|
||||
});
|
||||
|
||||
areaTable[WASTELAND_NEAR_COLOSSUS] = Area("Wasteland Near Colossus", "Haunted Wasteland", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
|
||||
Entrance(HAUNTED_WASTELAND, {[]{return LogicReverseWasteland || false;}}),
|
||||
});
|
||||
|
||||
areaTable[DESERT_COLOSSUS] = Area("Desert Colossus", "Desert Colossus", DESERT_COLOSSUS, DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPond, {[]{return FairyPond || CanPlay(SongOfStorms);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && CanTakeDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SongOfStorms;}}),
|
||||
EventAccess(&BugRock, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(COLOSSUS_FREESTANDING_POH, {[]{return IsAdult && CanPlantBean(DESERT_COLOSSUS);},
|
||||
/*Glitched*/[]{return (HoverBoots && CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED)) || (((IsChild && (ChildCanAccess(SPIRIT_TEMPLE_OUTDOOR_HANDS) || ChildCanAccess(SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND) || ChildCanAccess(SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND))) ||
|
||||
(IsAdult && (AdultCanAccess(SPIRIT_TEMPLE_OUTDOOR_HANDS) || AdultCanAccess(SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND) || AdultCanAccess(SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND)))) && (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::ADVANCED) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE)));}}),
|
||||
LocationAccess(SHEIK_AT_COLOSSUS, {[]{return true;}}),
|
||||
LocationAccess(COLOSSUS_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
|
||||
LocationAccess(COLOSSUS_GS_TREE, {[]{return IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(COLOSSUS_GS_HILL, {[]{return IsAdult && AtNight && (CanPlantBean(DESERT_COLOSSUS) || CanUse(LONGSHOT) || (LogicColossusGS && CanUse(HOOKSHOT))) && CanGetNightTimeGS;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::EXPERT) && CanShield && IsAdult && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(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);}}),
|
||||
});
|
||||
|
||||
areaTable[COLOSSUS_GREAT_FAIRY_FOUNTAIN] = Area("Colossus Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(COLOSSUS_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && CanTakeDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[COLOSSUS_GROTTO] = Area("Colossus Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
|
||||
});
|
||||
}
|
@ -0,0 +1,267 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_HyruleField() {
|
||||
areaTable[HYRULE_FIELD] = Area("Hyrule Field", "Hyrule Field", HYRULE_FIELD, DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&BigPoeKill, {[]{return CanUse(BOW) && CanRideEpona && HasBottle;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(HF_OCARINA_OF_TIME_ITEM, {[]{return IsChild && HasAllStones;}}),
|
||||
LocationAccess(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;});},
|
||||
/*Glitched*/[]{return Here(HYRULE_FIELD, []{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}}),
|
||||
Entrance(HF_OPEN_GROTTO, {[]{return true;}}),
|
||||
Entrance(HF_INSIDE_FENCE_GROTTO, {[]{return CanOpenBombGrotto;},
|
||||
/*Glitched*/[]{return Sticks && IsChild && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
|
||||
Entrance(HF_COW_GROTTO, {[]{return (CanUse(MEGATON_HAMMER) || IsChild) && CanOpenBombGrotto;},
|
||||
/*Glitched*/[]{return (CanUse(STICKS) && (ShardOfAgony || LogicGrottosWithoutAgony) && (IsChild || (CanOpenBombGrotto && (CanTakeDamageTwice || CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)))) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE));}}),
|
||||
Entrance(HF_NEAR_MARKET_GROTTO, {[]{return Here(HYRULE_FIELD, []{return CanBlastOrSmash;});},
|
||||
/*Glitched*/[]{return Here(HYRULE_FIELD, []{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}}),
|
||||
Entrance(HF_FAIRY_GROTTO, {[]{return Here(HYRULE_FIELD, []{return CanBlastOrSmash;});},
|
||||
/*Glitched*/[]{return Here(HYRULE_FIELD, []{return CanUse(STICKS) && ((IsChild && CanTakeDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::EXPERT)) || (IsAdult && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)));});}}),
|
||||
Entrance(HF_NEAR_KAK_GROTTO, {[]{return CanOpenBombGrotto;},
|
||||
/*Glitched*/[]{return Sticks && IsChild && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
|
||||
Entrance(HF_TEKTITE_GROTTO, {[]{return CanOpenBombGrotto;},
|
||||
/*Glitched*/[]{return Sticks && IsChild && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
|
||||
});
|
||||
|
||||
areaTable[HF_SOUTHEAST_GROTTO] = Area("HF Southeast Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||
//Locations
|
||||
LocationAccess(HF_SOUTHEAST_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(HF_SOUTHEAST_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[HF_OPEN_GROTTO] = Area("HF Open Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||
//Locations
|
||||
LocationAccess(HF_OPEN_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(HF_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[HF_INSIDE_FENCE_GROTTO] = Area("HF Inside Fence Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(HF_DEKU_SCRUB_GROTTO, {[]{return CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[HF_COW_GROTTO] = Area("HF Cow Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||
//Locations
|
||||
LocationAccess(HF_GS_COW_GROTTO, {[]{return HasFireSource && HookshotOrBoomerang;},
|
||||
/*Glitched*/[]{return (CanUse(STICKS) && Bombs && CanSurviveDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) && HookshotOrBoomerang;}}),
|
||||
LocationAccess(HF_COW_GROTTO_COW, {[]{return HasFireSource && CanPlay(EponasSong);},
|
||||
/*Glitched*/[]{return ((CanUse(STICKS) && Bombs && CanSurviveDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) || HasFireSource) &&
|
||||
(CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && Bombs && (CanSurviveDamage || (NumBottles >= 2 && Fairy)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)) || Ocarina) && EponasSong;}}),
|
||||
LocationAccess(HF_COW_GROTTO_GOSSIP_STONE, {[]{return HasFireSource;},
|
||||
/*Glitched*/[]{return CanUse(STICKS) && Bombs && CanSurviveDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[HF_NEAR_MARKET_GROTTO] = Area("HF Near Market Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||
//Locations
|
||||
LocationAccess(HF_NEAR_MARKET_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(HF_NEAR_MARKET_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[HF_FAIRY_GROTTO] = Area("HF Fairy Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[HF_NEAR_KAK_GROTTO] = Area("HF Near Kak Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(HF_GS_NEAR_KAK_GROTTO, {[]{return HookshotOrBoomerang;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[HF_TEKTITE_GROTTO] = Area("HF Tektite Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(HF_TEKTITE_GROTTO_FREESTANDING_POH, {[]{return ProgressiveScale >= 2 || CanUse(IRON_BOOTS);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LAKE_HYLIA] = Area("Lake Hylia", "Lake Hylia", 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(&BugShrub, {[]{return BugShrub || (IsChild && CanCutShrubs);}}),
|
||||
EventAccess(&ChildScarecrow, {[]{return ChildScarecrow || (IsChild && Ocarina);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && (KokiriSword || Sticks || Bombs || HasBombchus || Boomerang || Slingshot || CanUse(MEGATON_HAMMER)) && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE))) && IsChild;}}),
|
||||
EventAccess(&AdultScarecrow, {[]{return AdultScarecrow || (IsAdult && Ocarina);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE))) && IsAdult;}}),
|
||||
}, {
|
||||
//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));},
|
||||
/*Glitched*/[]{return (IsAdult && CanUse(HOOKSHOT) && ScarecrowSong && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
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;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::HookshotJump_Bonk, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::NOVICE)) && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(LH_LAB_GOSSIP_STONE, {[]{return true;}}),
|
||||
LocationAccess(LH_GOSSIP_STONE_SOUTHEAST, {[]{return true;}}),
|
||||
LocationAccess(LH_GOSSIP_STONE_SOUTHWEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
Entrance(ZORAS_DOMAIN, {[]{return IsChild && (CanDive || CanUse(IRON_BOOTS));},
|
||||
/*Glitched*/[]{return IsChild && (CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::NaviDive_Stick, GlitchDifficulty::INTERMEDIATE) ||
|
||||
(Bugs && CanUse(HOVER_BOOTS) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::INTERMEDIATE)) || (CanUse(FARORES_WIND) && (FaroresWindAnywhere || (CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && (HasBottle || (IsAdult && (HasBoots || ClaimCheck)) || (IsChild && WeirdEgg)))) &&
|
||||
((CanUse(NAYRUS_LOVE) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::NOVICE)) || (CanUseMagicArrow && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::ADVANCED)))));}}),
|
||||
Entrance(LH_OWL_FLIGHT, {[]{return IsChild;}}),
|
||||
Entrance(LH_FISHING_ISLAND, {[]{return IsChild || CanUse(SCARECROW) || CanPlantBean(LAKE_HYLIA) || WaterTempleClear;},
|
||||
/*Glitched*/[]{return (CanUse(HOOKSHOT) && ScarecrowSong && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::NOVICE)))) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE);}}),
|
||||
Entrance(LH_LAB, {[]{return true;}}),
|
||||
Entrance(WATER_TEMPLE_ENTRYWAY, {[]{return CanUse(HOOKSHOT) && (CanUse(IRON_BOOTS) || (IsAdult && CanUse(LONGSHOT) && ProgressiveScale >= 2));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::ADVANCED);}}),
|
||||
Entrance(LH_GROTTO, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LH_FISHING_ISLAND] = Area("LH Fishing Island", "Lake Hylia", LAKE_HYLIA, DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(LAKE_HYLIA, {[]{return true;}}),
|
||||
Entrance(LH_FISHING_HOLE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LH_OWL_FLIGHT] = Area("LH Owl Flight", "Lake Hylia", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LH_LAB] = Area("LH Lab", "", 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));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanUse(HOVER_BOOTS) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::INTERMEDIATE)) ||
|
||||
(CanUse(FARORES_WIND) && (FaroresWindAnywhere || (CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && (HasBottle || (IsAdult && (HasBoots || ClaimCheck)) || (IsChild && WeirdEgg)))) && CanUse(NAYRUS_LOVE) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::NOVICE));}}),
|
||||
LocationAccess(LH_TRADE_FROG, {[]{return IsAdult && EyeballFrog;}}),
|
||||
LocationAccess(LH_GS_LAB_CRATE, {[]{return CanUse(IRON_BOOTS) && CanUse(HOOKSHOT);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && HasBombchus && (HasBottle || (IsAdult && (HasBoots || ClaimCheck)) || (IsChild && WeirdEgg)) &&
|
||||
(CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanUse(HOVER_BOOTS) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::INTERMEDIATE)) ||
|
||||
(CanUse(FARORES_WIND) && CanUse(NAYRUS_LOVE) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::NOVICE)) || ProgressiveScale >= 2 || CanUse(IRON_BOOTS))) ||
|
||||
(CanUse(IRON_BOOTS) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LAKE_HYLIA, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LH_FISHING_HOLE] = Area("LH Fishing Hole", "", NONE, DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(LH_CHILD_FISHING, {[]{return IsChild;}}),
|
||||
LocationAccess(LH_ADULT_FISHING, {[]{return IsAdult;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LH_FISHING_ISLAND, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LH_GROTTO] = Area("LH Grotto", "", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LAKE_HYLIA, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LON_LON_RANCH] = Area("Lon Lon Ranch", "Lon Lon Ranch", 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;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && ZeldasLetter && 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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && IsChild && 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;}}),
|
||||
});
|
||||
|
||||
areaTable[LLR_TALONS_HOUSE] = Area("LLR Talons House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(LLR_TALONS_CHICKENS, {[]{return IsChild && AtDay && ZeldasLetter;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LON_LON_RANCH, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LLR_STABLES] = Area("LLR Stables", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(LLR_STABLES_LEFT_COW, {[]{return CanPlay(EponasSong);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE))) && EponasSong;}}),
|
||||
LocationAccess(LLR_STABLES_RIGHT_COW, {[]{return CanPlay(EponasSong);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE))) && EponasSong;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LON_LON_RANCH, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LLR_TOWER] = Area("LLR Tower", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(LLR_FREESTANDING_POH, {[]{return IsChild;}}),
|
||||
LocationAccess(LLR_TOWER_LEFT_COW, {[]{return CanPlay(EponasSong);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE))) && EponasSong;}}),
|
||||
LocationAccess(LLR_TOWER_RIGHT_COW, {[]{return CanPlay(EponasSong);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE))) && EponasSong;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LON_LON_RANCH, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LLR_GROTTO] = Area("LLR Grotto", "", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LON_LON_RANCH, {[]{return true;}}),
|
||||
});
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_IceCavern() {
|
||||
/*--------------------------
|
||||
| VANILLA/MQ DECIDER |
|
||||
---------------------------*/
|
||||
areaTable[ICE_CAVERN_ENTRYWAY] = Area("Ice Cavern Entryway", "Ice Cavern", 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;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::IceCavern.IsVanilla()) {
|
||||
areaTable[ICE_CAVERN_BEGINNING] = Area("Ice Cavern Beginning", "Ice Cavern", 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);});}}),
|
||||
});
|
||||
|
||||
areaTable[ICE_CAVERN_MAIN] = Area("Ice Cavern", "Ice Cavern", 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;}}),
|
||||
}, {});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {
|
||||
//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;}}),
|
||||
});
|
||||
|
||||
areaTable[ICE_CAVERN_MQ_MAP_ROOM] = Area("Ice Cavern MQ Map Room", "Ice Cavern", 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);}}),
|
||||
}, {});
|
||||
|
||||
areaTable[ICE_CAVERN_MQ_IRON_BOOTS_REGION] = Area("Ice Cavern MQ Iron Boots Region", "Ice Cavern", 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 IsAdult && (CanUse(SCARECROW) || (CanUse(HOVER_BOOTS) && CanUse(LONGSHOT)));}}),
|
||||
//Tricks: (CanUse(SCARECROW) || (HoverBoots && CanUse(LONGSHOT)) || LogicIceMQScarecrow) && IsAdult
|
||||
}, {});
|
||||
|
||||
areaTable[ICE_CAVERN_MQ_COMPASS_ROOM] = Area("Ice Cavern MQ Compass Room", "Ice Cavern", 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);}}),
|
||||
//Trick: CanPlay(SongOfTime) || LogicIceMQRedIceGS
|
||||
}, {});
|
||||
}
|
||||
}
|
@ -0,0 +1,245 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
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, {}, {}, {
|
||||
//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;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| 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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(JABU_JABUS_BELLY_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return CanUseProjectile;},
|
||||
/*Glitched*/[]{return CanUse(BOOMERANG) || CanUse(BOW) || CanUse(HOOKSHOT) || (CanUse(STICKS) && CanTakeDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::EXPERT)) || CanDoGlitch(GlitchType::SuperStab, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_LIFT_MIDDLE] = Area("Jabu Jabus Belly Lift Middle", "Jabu Jabus Belly", 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) || (LogicJabuBossGSAdult && IsAdult && CanUse(HOVER_BOOTS));},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)) &&
|
||||
GlitchJabuSwitch && (Fish || Bugs || CanUse(FARORES_WIND) || (IsAdult && ClaimCheck));}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_MAIN_UPPER] = Area("Jabu Jabus Belly Main Upper", "Jabu Jabus Belly", 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);});}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_MAIN_LOWER] = Area("Jabu Jabus Belly Main Lower", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER, {[]{return HookshotOrBoomerang;},
|
||||
/*Glitched*/[]{return Bombs && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
LocationAccess(JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER, {[]{return HookshotOrBoomerang;},
|
||||
/*Glitched*/[]{return Bombs && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
}, {
|
||||
//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;}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_SHABOMB_CORRIDOR] = Area("Jabu Jabus Belly Shabomb Corridor", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(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;},
|
||||
/*Glitched*/[]{return CanUse(BOOMERANG) || CanUse(BOW) || CanUse(HOOKSHOT) || (CanUse(STICKS) && CanTakeDamage && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::EXPERT));}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_LOWER_SIDE_ROOM] = Area("Jabu Jabus Belly Lower Side Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return FairyPot || (CanUse(BOOMERANG) || CanUse(HOVER_BOOTS));},
|
||||
/*Glitched*/[]{return (Bombs && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(JABU_JABUS_BELLY_DEKU_SCRUB, {[]{return (IsChild || CanDive || LogicJabuScrubJumpDive || CanUse(IRON_BOOTS)) && CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(JABU_JABUS_BELLY_SHABOMB_CORRIDOR, {[]{return true;}}),
|
||||
Entrance(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, {}, {}, {
|
||||
//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);});}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_BOOMERANG_ROOM] = Area("Jabu Jabus Belly Boomerang Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(JABU_JABUS_BELLY_BOOMERANG_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(JABU_JABUS_BELLY_MAP_CHEST, {[]{return CanUse(BOOMERANG);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(JABU_JABUS_BELLY_COMPASS_CHEST, {[]{return IsAdult || CanChildAttack;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return Here(JABU_JABUS_BELLY_BLUE_TENTACLE, []{return CanUse(BOOMERANG);});}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_GREEN_TENTACLE] = Area("Jabu Jabus Belly Green Tentacle", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(JABU_JABUS_BELLY_FORKED_CORRIDOR, {[]{return Here(JABU_JABUS_BELLY_GREEN_TENTACLE, []{return CanUse(BOOMERANG);});}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_BIGOCTO_ROOM] = Area("Jabu Jabus Belly Bigocto Room", "Jabu Jabus Belly", 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));});}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_ABOVE_BIGOCTO] = Area("Jabu Jabus Belly Above Bigocto", "Jabu Jabus Belly", 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);},
|
||||
/*Glitched*/[]{return HasBombchus && CanShield && IsAdult && (CanUse(HOOKSHOT) || CanUse(BOW) || CanUse(SLINGSHOT)) && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED);}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_LIFT_UPPER] = Area("Jabu Jabus Belly Lift Upper", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(JABU_JABUS_BELLY_GS_NEAR_BOSS, {[]{return IsAdult || CanChildAttack;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(JABU_JABUS_BELLY_LIFT_MIDDLE, {[]{return true;}}),
|
||||
Entrance(JABU_JABUS_BELLY_BOSS_ROOM, {[]{return CanUse(BOOMERANG);},
|
||||
/*Glitched*/[]{return (CanUse(HOVER_BOOTS) && (CanUse(BOW) || CanUse(SLINGSHOT))) || CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE) ||
|
||||
(CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::NOVICE)) || (Bombs && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::SuperStab, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_BOSS_ROOM] = Area("Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&JabuJabusBellyClear, {[]{return JabuJabusBellyClear || CanUse(BOOMERANG);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(JABU_JABUS_BELLY_BARINADE_HEART, {[]{return JabuJabusBellyClear;}}),
|
||||
LocationAccess(BARINADE, {[]{return JabuJabusBellyClear;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(JABU_JABUS_BELLY_NEAR_BOSS_ROOM, {[]{return JabuJabusBellyClear;}}),
|
||||
Entrance(JABU_JABUS_BELLY_ENTRYWAY, {[]{return JabuJabusBellyClear;}}),
|
||||
});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {
|
||||
//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);}}),
|
||||
}, {
|
||||
//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);});}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_MQ_MAIN] = Area("Jabu Jabus Belly MQ Main", "Jabu Jabus Belly", 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);}}),
|
||||
//Trick: CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(BOOMERANG))
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}),
|
||||
Entrance(JABU_JABUS_BELLY_MQ_DEPTHS, {[]{return HasExplosives && IsChild && CanUse(BOOMERANG);}}),
|
||||
});
|
||||
|
||||
areaTable[JABU_JABUS_BELLY_MQ_DEPTHS] = Area("Jabu Jabus Belly MQ Depths", "Jabu Jabus Belly", 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);});}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}),
|
||||
Entrance(JABU_JABUS_BELLY_MQ_BOSS_AREA, {[]{return Sticks || (CanUse(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, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return true;}}),
|
||||
EventAccess(&JabuJabusBellyClear, {[]{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_BARINADE_HEART, {[]{return true;}}),
|
||||
LocationAccess(BARINADE, {[]{return true;}}),
|
||||
LocationAccess(JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}),
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,303 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_Kakariko() {
|
||||
areaTable[KAKARIKO_VILLAGE] = Area("Kakariko Village", "Kakariko Village", 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)) && AtNight && CanGetNightTimeGS;},
|
||||
/*Glitched*/[]{return IsChild && AtNight && CanGetNightTimeGS && (CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::SuperStab, GlitchDifficulty::NOVICE) || (Sticks && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE)));}}),
|
||||
LocationAccess(KAK_GS_ABOVE_IMPAS_HOUSE, {[]{return IsAdult && CanUse(HOOKSHOT) && AtNight && CanGetNightTimeGS;},
|
||||
/*Glitched*/[]{return IsAdult && AtNight && CanGetNightTimeGS && ((HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::NOVICE);}}),
|
||||
Entrance(KAK_SHOOTING_GALLERY, {[]{return IsAdult && AtDay;}}),
|
||||
Entrance(BOTTOM_OF_THE_WELL_ENTRYWAY, {[]{return DrainWell && (IsChild || ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF));},
|
||||
/*Glitched*/[]{return (IsChild && (CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::NOVICE) || (AtNight && (CanDoGlitch(GlitchType::NaviDive_Stick, GlitchDifficulty::NOVICE) || ((Bugs || Fish) && CanUse(HOVER_BOOTS) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::INTERMEDIATE)) ||
|
||||
(CanUse(FARORES_WIND) && (FaroresWindAnywhere || (CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && (HasBottle || WeirdEgg))) && ((CanUse(NAYRUS_LOVE) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::NOVICE)) ||
|
||||
(CanUseMagicArrow && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::ADVANCED)))))))) || (IsAdult && CanUse(LONGSHOT) && AtDay && CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::NOVICE));}}),
|
||||
Entrance(KAK_POTION_SHOP_FRONT, {[]{return AtDay || IsChild;}}),
|
||||
Entrance(KAK_REDEAD_GROTTO, {[]{return CanOpenBombGrotto;}}),
|
||||
Entrance(KAK_IMPAS_LEDGE, {[]{return (IsChild && AtDay) || CanUse(HOOKSHOT);},
|
||||
/*Glitched*/[]{return IsAdult && ((HoverBoots && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE)) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
Entrance(KAK_ROOFTOP, {[]{return CanUse(HOOKSHOT) || (LogicManOnRoof && (IsAdult || AtDay || Slingshot || HasBombchus || CanUse(BOW) || CanUse(LONGSHOT)));},
|
||||
/*Glitched*/[]{return LogicManOnRoof && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE);}}),
|
||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||
Entrance(KAK_BEHIND_GATE, {[]{return IsAdult || (KakarikoVillageGateOpen);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_IMPAS_LEDGE] = Area("Kak Impas Ledge", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KAK_IMPAS_HOUSE_BACK, {[]{return true;}}),
|
||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_ROOFTOP] = Area("Kak Rooftop", "Kakariko Village", KAKARIKO_VILLAGE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(KAK_MAN_ON_ROOF, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KAK_BACKYARD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_BACKYARD] = Area("Kak Backyard", "Kakariko Village", 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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_CARPENTER_BOSS_HOUSE] = Area("Kak Carpenter Boss House", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&WakeUpAdultTalon, {[]{return WakeUpAdultTalon || (IsAdult && PocketEgg);}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_HOUSE_OF_SKULLTULA] = Area("Kak House of Skulltula", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(KAK_10_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 10;}}),
|
||||
LocationAccess(KAK_20_GOLD_SKULLTULA_REWARD, {[]{return GoldSkulltulaTokens >= 20;}}),
|
||||
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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_IMPAS_HOUSE] = Area("Kak Impas House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
|
||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_IMPAS_HOUSE_BACK] = Area("Kak Impas House Back", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(KAK_IMPAS_HOUSE_FREESTANDING_POH, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KAK_IMPAS_LEDGE, {[]{return true;}}),
|
||||
Entrance(KAK_IMPAS_HOUSE_NEAR_COW, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_IMPAS_HOUSE_NEAR_COW] = Area("Kak Impas House Near Cow", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(KAK_IMPAS_HOUSE_COW, {[]{return CanPlay(EponasSong);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED))) && EponasSong;}}),
|
||||
}, {});
|
||||
|
||||
areaTable[KAK_WINDMILL] = Area("Kak Windmill", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&DrainWell, {[]{return DrainWell || (IsChild && CanPlay(SongOfStorms));},
|
||||
/*Glitched*/[]{return IsChild && SongOfStorms && (CanDoGlitch(GlitchType::WindmillBombOI, GlitchDifficulty::ADVANCED) || ((Fish || Bugs) && CanShield && ((Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2))) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE)) &&
|
||||
CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Fish || Bugs) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(KAK_WINDMILL_FREESTANDING_POH, {[]{return CanUse(BOOMERANG) || DampesWindmillAccess || (IsAdult && CanUse(HOOKSHOT) && LogicWindmillPoHHookshot);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
LocationAccess(SONG_FROM_WINDMILL, {[]{return IsAdult && Ocarina;},
|
||||
/*Glitched*/[]{return IsAdult && (CanDoGlitch(GlitchType::WindmillBombOI, GlitchDifficulty::EXPERT) || ((Fish || Bugs) && CanShield && ((Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2))) || (DampesWindmillAccess || (IsAdult && CanUse(HOOKSHOT) && LogicWindmillPoHHookshot) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE))) &&
|
||||
CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Fish || Bugs) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_BAZAAR] = Area("Kak Bazaar", "", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_SHOOTING_GALLERY] = Area("Kak Shooting Gallery", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(KAK_SHOOTING_GALLERY_REWARD, {[]{return IsAdult && Bow;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_POTION_SHOP_FRONT] = Area("Kak Potion Shop Front", "", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KAKARIKO_VILLAGE, {[]{return true;}}),
|
||||
Entrance(KAK_POTION_SHOP_BACK, {[]{return IsAdult;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_POTION_SHOP_BACK] = Area("Kak Potion Shop Back", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KAK_BACKYARD, {[]{return IsAdult;}}),
|
||||
Entrance(KAK_POTION_SHOP_FRONT, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_ODD_POTION_BUILDING] = Area("Kak Granny's Potion Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&OddPoulticeAccess, {[]{return OddPoulticeAccess || (IsAdult && (OddMushroomAccess || (OddMushroom && DisableTradeRevert)));}}),
|
||||
}, {
|
||||
LocationAccess(KAK_TRADE_ODD_MUSHROOM, {[]{return IsAdult && OddMushroom;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KAK_BACKYARD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_REDEAD_GROTTO] = Area("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", "", 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(&BugRock, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GRAVEYARD_FREESTANDING_POH, {[]{return (IsAdult && CanPlantBean(THE_GRAVEYARD)) || CanUse(LONGSHOT) || (LogicGraveyardPoH && CanUse(BOOMERANG));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HookshotJump_Bonk, GlitchDifficulty::NOVICE);}}),
|
||||
LocationAccess(GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, {[]{return IsChild && AtNight;}}), //TODO: This needs to change
|
||||
LocationAccess(GRAVEYARD_GS_WALL, {[]{return IsChild && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;},
|
||||
/*Glitched*/[]{return IsChild && AtNight && CanGetNightTimeGS && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
LocationAccess(GRAVEYARD_GS_BEAN_PATCH, {[]{return CanPlantBugs && CanChildAttack;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(GRAVEYARD_SHIELD_GRAVE, {[]{return IsAdult || AtNight;}}),
|
||||
Entrance(GRAVEYARD_COMPOSERS_GRAVE, {[]{return CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) || ((Bugs || Fish) && CanShield && (IsChild || AdultCanAccess(GRAVEYARD_WARP_PAD_REGION) || (IsAdult && (CanPlantBean(THE_GRAVEYARD) || CanUse(LONGSHOT))) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || (Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2)))) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && 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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HookshotJump_Bonk, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
|
||||
areaTable[GRAVEYARD_SHIELD_GRAVE] = Area("Graveyard Shield Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(GRAVEYARD_SHIELD_GRAVE_CHEST, {[]{return true;}}),
|
||||
//Free Fairies
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GRAVEYARD_HEART_PIECE_GRAVE] = Area("Graveyard Heart Piece Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(GRAVEYARD_HEART_PIECE_GRAVE_CHEST, {[]{return CanPlay(SunsSong);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::NOVICE) || ((Bugs || Fish) && CanShield && (Bombs && (CanSurviveDamage || (Fairy && NumBottles >= 2))) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SunsSong;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GRAVEYARD_COMPOSERS_GRAVE] = Area("Graveyard Composers Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(GRAVEYARD_COMPOSERS_GRAVE_CHEST, {[]{return HasFireSource;},
|
||||
/*Glitched*/[]{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
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));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GRAVEYARD_DAMPES_GRAVE] = Area("Graveyard Dampes Grave", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&NutPot, {[]{return true;}}),
|
||||
EventAccess(&DampesWindmillAccess, {[]{return DampesWindmillAccess || (IsAdult && CanPlay(SongOfTime));},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::WindmillBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsAdult && SongOfTime;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GRAVEYARD_HOOKSHOT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, {[]{return IsAdult || LogicChildDampeRacePoH;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||
Entrance(KAK_WINDMILL, {[]{return IsAdult && CanPlay(SongOfTime);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::WindmillBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsAdult && SongOfTime;}}),
|
||||
});
|
||||
|
||||
areaTable[GRAVEYARD_DAMPES_HOUSE] = Area("Graveyard Dampes House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[GRAVEYARD_WARP_PAD_REGION] = Area("Graveyard Warp Pad Region", "Graveyard", THE_GRAVEYARD, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(GRAVEYARD_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_GRAVEYARD, {[]{return true;}}),
|
||||
Entrance(SHADOW_TEMPLE_ENTRYWAY, {[]{return CanUse(DINS_FIRE) || (LogicShadowFireArrowEntry && IsAdult && CanUse(FIRE_ARROWS));},
|
||||
/*Glitched*/[]{return (CanUse(STICKS) && (CanDoGlitch(GlitchType::QPA, GlitchDifficulty::INTERMEDIATE) || CanUse(FIRE_ARROWS))) || (CanTakeDamage && (
|
||||
CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HookshotJump_Bonk, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::NOVICE)));}}),
|
||||
});
|
||||
|
||||
areaTable[KAK_BEHIND_GATE] = Area("Kak Behind Gate", "Kakariko Village", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KAKARIKO_VILLAGE, {[]{return IsAdult || LogicVisibleCollision || KakarikoVillageGateOpen || OpenKakariko.Is(OPENKAKARIKO_OPEN);}}),
|
||||
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
|
||||
});
|
||||
}
|
@ -0,0 +1,275 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_LostWoods() {
|
||||
areaTable[KOKIRI_FOREST] = Area("Kokiri Forest", "Kokiri Forest", KOKIRI_FOREST, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || (CanPlantBean(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 && CanGetNightTimeGS;},
|
||||
/*Glitched*/[]{return IsAdult && AtNight && CanGetNightTimeGS && (CanDoGlitch(GlitchType::HammerSlide, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
LocationAccess(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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::LedgeCancel, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(THE_LOST_WOODS, {[]{return true;}}),
|
||||
Entrance(LW_BRIDGE_FROM_FOREST, {[]{return IsAdult || OpenForest.IsNot(OPENFOREST_CLOSED) || DekuTreeClear;},
|
||||
/*Glitched*/[]{return CanLeaveForest && (CanDoGlitch(GlitchType::LedgeCancel, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || GlitchWWTEscape);}}),
|
||||
Entrance(KF_STORMS_GROTTO, {[]{return CanOpenStormGrotto;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
||||
});
|
||||
|
||||
areaTable[KF_OUTSIDE_DEKU_TREE] = Area("KF Outside Deku Tree", "Kokiri Forest", 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(&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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DEKU_TREE_ENTRYWAY, {[]{return IsChild || (ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF) && (OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HammerSlide, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(KOKIRI_FOREST, {[]{return IsAdult || OpenForest.Is(OPENFOREST_OPEN) || ShowedMidoSwordAndShield;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
});
|
||||
|
||||
areaTable[KF_LINKS_HOUSE] = Area("KF Link's House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(KF_LINKS_HOUSE_COW, {[]{return IsAdult && CanPlay(EponasSong) && LinksCow;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::IndoorBombOI, GlitchDifficulty::EXPERT) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (NumBottles >= 2 && Fairy)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::EXPERT))) && CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && Bombs && IsAdult && EponasSong && LinksCow;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KOKIRI_FOREST, {[]{return true;}})
|
||||
});
|
||||
|
||||
areaTable[KF_MIDOS_HOUSE] = Area("KF Mido's House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(KF_MIDOS_TOP_LEFT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(KF_MIDOS_TOP_RIGHT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(KF_MIDOS_BOTTOM_LEFT_CHEST, {[]{return true;}}),
|
||||
LocationAccess(KF_MIDOS_BOTTOM_RIGHT_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KF_SARIAS_HOUSE] = Area("KF Saria's House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KF_HOUSE_OF_TWINS] = Area("KF House of Twins", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KF_KNOW_IT_ALL_HOUSE] = Area("KF Know It All House", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KF_KOKIRI_SHOP] = Area("KF Kokiri Shop", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KOKIRI_FOREST, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[KF_STORMS_GROTTO] = Area("KF Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||
//Locations
|
||||
LocationAccess(KF_STORMS_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(KF_STORMS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(KOKIRI_FOREST, {[]{return true;}})
|
||||
});
|
||||
|
||||
areaTable[LW_FOREST_EXIT] = Area("LW Forest Exit", "Lost Woods", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(KOKIRI_FOREST, {[]{return true;}})
|
||||
});
|
||||
|
||||
areaTable[THE_LOST_WOODS] = Area("Lost Woods", "Lost Woods", THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&OddMushroomAccess, {[]{return OddMushroomAccess || (IsAdult && (CojiroAccess || Cojiro));}}),
|
||||
EventAccess(&PoachersSawAccess, {[]{return PoachersSawAccess || (IsAdult && OddPoulticeAccess);}}),
|
||||
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
|
||||
EventAccess(&BeanPlantFairy, {[]{return BeanPlantFairy || CanPlay(SongOfStorms);}}),
|
||||
EventAccess(&BugShrub, {[]{return IsChild && CanCutShrubs;},
|
||||
/*Glitched*/[]{return IsChild && Sticks && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(LW_SKULL_KID, {[]{return IsChild && CanPlay(SariasSong);},
|
||||
/*Glitched*/[]{return IsChild && (Fish || Bugs) && SariasSong && CanShield && (CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) || (HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)));}}),
|
||||
LocationAccess(LW_TRADE_COJIRO, {[]{return IsAdult && Cojiro;}}),
|
||||
LocationAccess(LW_TRADE_ODD_POTION, {[]{return IsAdult && OddPoultice && Cojiro;}}),
|
||||
LocationAccess(LW_OCARINA_MEMORY_GAME, {[]{return IsChild && Ocarina;},
|
||||
/*Glitched*/[]{return IsChild && (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Fish || Bugs) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)));}}),
|
||||
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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LW_FOREST_EXIT, {[]{return true;}}),
|
||||
Entrance(GC_WOODS_WARP, {[]{return true;}}),
|
||||
Entrance(LW_BRIDGE, {[]{return CanLeaveForest && ((IsAdult && CanPlantBean(THE_LOST_WOODS)) || CanUse(HOVER_BOOTS) || CanUse(LONGSHOT));},
|
||||
/*Glitched*/[]{return CanLeaveForest && (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) || (CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && HasBombchus) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
Entrance(ZORAS_RIVER, {[]{return CanLeaveForest && (CanDive || CanUse(IRON_BOOTS));},
|
||||
/*Glitched*/[]{return CanLeaveForest && (CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::NaviDive_Stick, GlitchDifficulty::ADVANCED) ||
|
||||
((Bugs || Fish) && CanUse(HOVER_BOOTS) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::INTERMEDIATE)) || (CanUse(FARORES_WIND) && (FaroresWindAnywhere || (CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && (HasBottle || (IsAdult && (HasBoots || ClaimCheck)) || (IsChild && WeirdEgg)))) &&
|
||||
((CanUse(NAYRUS_LOVE) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::NOVICE)) || (CanUseMagicArrow && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::ADVANCED)))));}}),
|
||||
Entrance(LW_BEYOND_MIDO, {[]{return IsChild || CanPlay(SariasSong);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::LedgeCancel, GlitchDifficulty::NOVICE) ||
|
||||
CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE) || (CanDoGlitch(GlitchType::HookshotJump_Bonk, GlitchDifficulty::ADVANCED) && (CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE) || HoverBoots)) ||
|
||||
((CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SariasSong);}}),
|
||||
Entrance(LW_NEAR_SHORTCUTS_GROTTO, {[]{return Here(THE_LOST_WOODS, []{return CanBlastOrSmash;});},
|
||||
/*Glitched*/[]{return Here(THE_LOST_WOODS, []{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}}),
|
||||
});
|
||||
|
||||
areaTable[LW_BEYOND_MIDO] = Area("LW Beyond Mido", "Lost Woods", THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || CanUse(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;},
|
||||
/*Glitched*/[]{return IsAdult && AtNight && CanGetNightTimeGS && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
LocationAccess(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);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE) || ((CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) ||
|
||||
((Bugs || Fish) && CanShield && Bombs && (CanSurviveDamage || (NumBottles >= 2 && Fairy)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SariasSong);}}),
|
||||
Entrance(SFM_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(DEKU_THEATER, {[]{return true;}}),
|
||||
Entrance(LW_SCRUBS_GROTTO, {[]{return Here(LW_BEYOND_MIDO, []{return CanBlastOrSmash;});},
|
||||
/*Glitched*/[]{return Here(LW_BEYOND_MIDO, []{return IsChild && CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}}),
|
||||
});
|
||||
|
||||
areaTable[LW_NEAR_SHORTCUTS_GROTTO] = Area("LW Near Shortcuts Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||
//Locations
|
||||
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(LW_NEAR_SHORTCUTS_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(THE_LOST_WOODS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[DEKU_THEATER] = Area("Deku Theater", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(DEKU_THEATER_SKULL_MASK, {[]{return IsChild && SkullMask;}}),
|
||||
LocationAccess(DEKU_THEATER_MASK_OF_TRUTH, {[]{return IsChild && MaskOfTruth;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LW_BEYOND_MIDO, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LW_SCRUBS_GROTTO] = Area("LW Scrubs Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(LW_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(LW_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LW_BEYOND_MIDO, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[SFM_ENTRYWAY] = Area("SFM Entryway", "Sacred Forest Meadow", 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;}}),
|
||||
});
|
||||
|
||||
areaTable[SACRED_FOREST_MEADOW] = Area("Sacred Forest Meadow", "Sacred Forest Meadow", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SFM_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(FOREST_TEMPLE_ENTRYWAY, {[]{return CanUse(HOOKSHOT);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(SFM_FAIRY_GROTTO, {[]{return true;}}),
|
||||
Entrance(SFM_STORMS_GROTTO, {[]{return CanOpenStormGrotto;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && HasBombchus && CanShield && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
||||
});
|
||||
|
||||
areaTable[SFM_FAIRY_GROTTO] = Area("SFM Fairy Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[SFM_WOLFOS_GROTTO] = Area("SFM Wolfos Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(SFM_WOLFOS_GROTTO_CHEST, {[]{return IsAdult || Slingshot || Sticks || KokiriSword || CanUse(DINS_FIRE) || CanUse(MEGATON_HAMMER) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SFM_ENTRYWAY, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[SFM_STORMS_GROTTO] = Area("SFM Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(SFM_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(SFM_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SACRED_FOREST_MEADOW, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LW_BRIDGE_FROM_FOREST] = Area("LW Bridge From Forest", "Lost Woods", THE_LOST_WOODS, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(LW_GIFT_FROM_SARIA, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(LW_BRIDGE, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[LW_BRIDGE] = Area("LW Bridge", "Lost Woods", 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);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && Bombs && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)) || CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HookshotJump_Bonk, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_ShadowTemple() {
|
||||
/*--------------------------
|
||||
| VANILLA/MQ DECIDER |
|
||||
---------------------------*/
|
||||
areaTable[SHADOW_TEMPLE_ENTRYWAY] = Area("Shadow Temple Entryway", "Shadow Temple", 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));},
|
||||
/*Glitched*/[]{return Dungeon::ShadowTemple.IsVanilla() && (LogicLensShadow || CanUse(LENS_OF_TRUTH)) && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(SHADOW_TEMPLE_MQ_BEGINNING, {[]{return Dungeon::ShadowTemple.IsMQ() && (LogicLensShadowMQ || CanUse(LENS_OF_TRUTH)) && (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT));},
|
||||
/*Glitched*/[]{return Dungeon::ShadowTemple.IsMQ() && (LogicLensShadowMQ || CanUse(LENS_OF_TRUTH)) && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(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, {
|
||||
//Events
|
||||
EventAccess(&NutPot, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(SHADOW_TEMPLE_MAP_CHEST, {[]{return true;}}),
|
||||
LocationAccess(SHADOW_TEMPLE_HOVER_BOOTS_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SHADOW_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(SHADOW_TEMPLE_FIRST_BEAMOS, {[]{return HoverBoots;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::NOVICE);}}),
|
||||
});
|
||||
|
||||
areaTable[SHADOW_TEMPLE_FIRST_BEAMOS] = Area("Shadow Temple First Beamos", "Shadow Temple", 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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE) && Longshot;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SHADOW_TEMPLE_HUGE_PIT, {[]{return HasExplosives && IsAdult && SmallKeys(SHADOW_TEMPLE, 1, 2);}}),
|
||||
Entrance(SHADOW_TEMPLE_BEYOND_BOAT, {[]{return false;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE) && Longshot && CanPlay(ZeldasLullaby);}}),
|
||||
});
|
||||
|
||||
areaTable[SHADOW_TEMPLE_HUGE_PIT] = Area("Shadow Temple Huge Pit", "Shadow Temple", 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 || GoronBracelet;}}),
|
||||
LocationAccess(SHADOW_TEMPLE_FALLING_SPIKES_SWITCH_CHEST, {[]{return LogicShadowUmbrella || GoronBracelet;}}),
|
||||
LocationAccess(SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, {[]{return SmallKeys(SHADOW_TEMPLE, 2, 3) && (LogicLensShadowBack || CanUse(LENS_OF_TRUTH));}}),
|
||||
LocationAccess(SHADOW_TEMPLE_FREESTANDING_KEY, {[]{return SmallKeys(SHADOW_TEMPLE, 2, 3) && (LogicLensShadowBack || 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;}}),
|
||||
LocationAccess(SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, {[]{return SmallKeys(SHADOW_TEMPLE, 2, 3) && (LogicLensShadowBack || CanUse(LENS_OF_TRUTH)) && Hookshot;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SHADOW_TEMPLE_WIND_TUNNEL, {[]{return (LogicLensShadowBack || CanUse(LENS_OF_TRUTH)) && Hookshot && SmallKeys(SHADOW_TEMPLE, 3, 4);}}),
|
||||
});
|
||||
|
||||
areaTable[SHADOW_TEMPLE_WIND_TUNNEL] = Area("Shadow Temple Wind Tunnel", "Shadow Temple", 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);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SHADOW_TEMPLE_BEYOND_BOAT, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(SHADOW_TEMPLE, 4, 5);}}),
|
||||
});
|
||||
|
||||
areaTable[SHADOW_TEMPLE_BEYOND_BOAT] = Area("Shadow Temple Beyond Boat", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ShadowTempleClear, {[]{return ShadowTempleClear || (SmallKeys(SHADOW_TEMPLE, 5) && BossKeyShadowTemple && (Bow || CanUse(DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus)));}}),
|
||||
}, {
|
||||
//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_BONGO_BONGO_HEART, {[]{return SmallKeys(SHADOW_TEMPLE, 5) && BossKeyShadowTemple && (Bow || CanUse(DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus));}}),
|
||||
LocationAccess(BONGO_BONGO, {[]{return SmallKeys(SHADOW_TEMPLE, 5) && BossKeyShadowTemple && (Bow || CanUse(DISTANT_SCARECROW) || (LogicShadowStatue && HasBombchus));}}),
|
||||
LocationAccess(SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT, {[]{return true;}}),
|
||||
}, {});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(SHADOW_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(SHADOW_TEMPLE_MQ_FIRST_BEAMOS, {[]{return IsAdult && (CanUse(FIRE_ARROWS) || CanUse(HOVER_BOOTS));}}),
|
||||
//Trick: IsAdult && (CanUse(FIRE_ARROWS) || HoverBoots || (LogicShadowMQGap && CanUse(LONGSHOT)))
|
||||
Entrance(SHADOW_TEMPLE_MQ_DEAD_HAND_AREA, {[]{return HasExplosives && SmallKeys(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(SHADOW_TEMPLE_MQ_COMPASS_CHEST, {[]{return true;}}),
|
||||
LocationAccess(SHADOW_TEMPLE_MQ_HOVER_BOOTS_CHEST, {[]{return CanPlay(SongOfTime) && IsAdult && CanUse(BOW);}}),
|
||||
}, {});
|
||||
|
||||
areaTable[SHADOW_TEMPLE_MQ_FIRST_BEAMOS] = Area("Shadow Temple MQ First Beamos", "Shadow Temple", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, {[]{return HasExplosives && SmallKeys(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, {[]{return CanPlay(SongOfTime);}}),
|
||||
//Trick: CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
|
||||
LocationAccess(SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, {[]{return CanPlay(SongOfTime);}}),
|
||||
//Trick: CanPlay(SongOfTime) || (LogicShadowMQInvisibleBlades && DamageMultiplier.IsNot(DAMAGEMULTIPLIER_OHKO))
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, {[]{return HasFireSource;}}),
|
||||
//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, {}, {
|
||||
//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) && (LogicLensShadowMQBack || CanUse(LENS_OF_TRUTH));}}),
|
||||
LocationAccess(SHADOW_TEMPLE_MQ_STALFOS_ROOM_CHEST, {[]{return HoverBoots && SmallKeys(SHADOW_TEMPLE, 3) && Hookshot && (LogicLensShadowMQBack || CanUse(LENS_OF_TRUTH));}}),
|
||||
LocationAccess(SHADOW_TEMPLE_MQ_GS_FALLING_SPIKES_ROOM, {[]{return Hookshot;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SHADOW_TEMPLE_MQ_WIND_TUNNEL, {[]{return HoverBoots && (LogicLensShadowMQBack || CanUse(LENS_OF_TRUTH)) && Hookshot && SmallKeys(SHADOW_TEMPLE, 4);}}),
|
||||
});
|
||||
|
||||
areaTable[SHADOW_TEMPLE_MQ_WIND_TUNNEL] = Area("Shadow Temple MQ Wind Tunnel", "Shadow Temple", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SHADOW_TEMPLE_MQ_BEYOND_BOAT, {[]{return CanPlay(ZeldasLullaby) && SmallKeys(SHADOW_TEMPLE, 5);}}),
|
||||
});
|
||||
|
||||
areaTable[SHADOW_TEMPLE_MQ_BEYOND_BOAT] = Area("Shadow Temple MQ Beyond Boat", "Shadow Temple", SHADOW_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&ShadowTempleClear, {[]{return ShadowTempleClear || ((Bow || (LogicShadowStatue && HasBombchus)) && BossKeyShadowTemple);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(SHADOW_TEMPLE_BONGO_BONGO_HEART, {[]{return (Bow || (LogicShadowStatue && HasBombchus)) && BossKeyShadowTemple;}}),
|
||||
LocationAccess(BONGO_BONGO, {[]{return (Bow || (LogicShadowStatue && HasBombchus)) && BossKeyShadowTemple;}}),
|
||||
LocationAccess(SHADOW_TEMPLE_MQ_GS_AFTER_SHIP, {[]{return true;}}),
|
||||
LocationAccess(SHADOW_TEMPLE_MQ_GS_NEAR_BOSS, {[]{return Bow || (LogicShadowStatue && HasBombchus);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SHADOW_TEMPLE_MQ_INVISIBLE_MAZE, {[]{return Bow && CanPlay(SongOfTime) && IsAdult && CanUse(LONGSHOT);}}),
|
||||
});
|
||||
|
||||
areaTable[SHADOW_TEMPLE_MQ_INVISIBLE_MAZE] = Area("Shadow Temple MQ Invisible Maze", "Shadow Temple", 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(SHADOW_TEMPLE_MQ_BOMB_FLOWER_CHEST, {[]{return true;}}),
|
||||
LocationAccess(SHADOW_TEMPLE_MQ_FREESTANDING_KEY, {[]{return true;}}),
|
||||
}, {});
|
||||
}
|
||||
}
|
@ -0,0 +1,232 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_SpiritTemple() {
|
||||
/*--------------------------
|
||||
| VANILLA/MQ DECIDER |
|
||||
---------------------------*/
|
||||
areaTable[SPIRIT_TEMPLE_ENTRYWAY] = Area("Spirit Temple Entryway", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(SPIRIT_TEMPLE_LOBBY, {[]{return Dungeon::SpiritTemple.IsVanilla();}}),
|
||||
Entrance(SPIRIT_TEMPLE_MQ_LOBBY, {[]{return Dungeon::SpiritTemple.IsMQ();}}),
|
||||
Entrance(DESERT_COLOSSUS, {[]{return true;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
if (Dungeon::SpiritTemple.IsVanilla()) {
|
||||
areaTable[SPIRIT_TEMPLE_LOBBY] = Area("Spirit Temple Lobby", "Spirit Temple", 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);}}),
|
||||
});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_CHILD] = Area("Child Spirit Temple", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&NutCrate, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, {[]{return (Boomerang || Slingshot || (HasExplosives && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}),
|
||||
LocationAccess(SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, {[]{return (Boomerang || Slingshot || (HasExplosives && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot))) && (Sticks || CanUse(DINS_FIRE));}}),
|
||||
LocationAccess(SPIRIT_TEMPLE_GS_METAL_FENCE, {[]{return (Boomerang || Slingshot || (HasExplosives && LogicSpiritChildBombchu)) && (HasExplosives || ((Nuts || Boomerang) && (Sticks || KokiriSword || Slingshot)));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SPIRIT_TEMPLE_CHILD_CLIMB, {[]{return SmallKeys(SPIRIT_TEMPLE, 1);}}),
|
||||
});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_CHILD_CLIMB] = Area("Child Spirit Temple Climb", "Spirit Temple", 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) ||
|
||||
(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));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return HasExplosives;}}),
|
||||
});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_EARLY_ADULT] = Area("Early Adult Spirit Temple", "Spirit Temple", 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));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SPIRIT_TEMPLE_CENTRAL_CHAMBER, {[]{return SmallKeys(SPIRIT_TEMPLE, 1);}}),
|
||||
});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Area("Spirit Temple Central Chamber", "Spirit Temple", 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))) &&
|
||||
|
||||
(CanUse(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) ||
|
||||
(((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);}}),
|
||||
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))) &&
|
||||
LogicSpiritLobbyGS && Boomerang && (Hookshot || HoverBoots)) ||
|
||||
(LogicSpiritLobbyGS && SmallKeys(SPIRIT_TEMPLE, 5) && HasExplosives && CanUse(BOOMERANG)) ||
|
||||
(SmallKeys(SPIRIT_TEMPLE, 3) && CanUse(SILVER_GAUNTLETS) && (Hookshot || HoverBoots));}}),
|
||||
}, {
|
||||
//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;}}),
|
||||
});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_OUTDOOR_HANDS] = Area("Spirit Temple Outdoor Hands", "Spirit Temple", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(DESERT_COLOSSUS, {[]{return (IsChild && SmallKeys(SPIRIT_TEMPLE, 5)) || (CanUse(SILVER_GAUNTLETS) && ((SmallKeys(SPIRIT_TEMPLE, 3) && HasExplosives) || SmallKeys(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, {[]{return MirrorShield && 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;}}),
|
||||
}, {
|
||||
//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)));}}),
|
||||
});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_BEYOND_FINAL_LOCKED_DOOR] = Area("Spirit Temple Beyond Final Locked Door", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&SpiritTempleClear, {[]{return SpiritTempleClear || (MirrorShield && HasExplosives && Hookshot && BossKeySpiritTemple);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(SPIRIT_TEMPLE_BOSS_KEY_CHEST, {[]{return CanPlay(ZeldasLullaby) && ((CanTakeDamage && LogicFlamingChests) || (Bow && Hookshot));}}),
|
||||
LocationAccess(SPIRIT_TEMPLE_TOPMOST_CHEST, {[]{return MirrorShield;}}),
|
||||
LocationAccess(SPIRIT_TEMPLE_TWINROVA_HEART, {[]{return MirrorShield && HasExplosives && Hookshot && BossKeySpiritTemple;}}),
|
||||
LocationAccess(TWINROVA, {[]{return MirrorShield && HasExplosives && Hookshot && BossKeySpiritTemple;}}),
|
||||
}, {});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {}, {
|
||||
//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)));}}),
|
||||
}, {
|
||||
//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);}}),
|
||||
});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_MQ_CHILD] = Area("Spirit Temple MQ Child", "Spirit Temple", 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);})));}}),
|
||||
//Trick: HasBombchus && SmallKeys(SPIRIT_TEMPLE, 7) && Slingshot && (CanUse(DINS_FIRE) || (SPIRIT_TEMPLE_MQ_ADULT.Adult() && IsAdult && (CanUse(FIRE_ARROWS) || (LogicSpiritMQFrozenEye && CanUse(BOW) && CanPlay(SongOfTime)))))
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SPIRIT_TEMPLE_MQ_SHARED, {[]{return HasBombchus && SmallKeys(SPIRIT_TEMPLE, 2);}}),
|
||||
});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_MQ_ADULT] = Area("Spirit Temple MQ Adult", "Spirit Temple", 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;}}),
|
||||
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);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SPIRIT_TEMPLE_MQ_LOWER_ADULT, {[]{return MirrorShield && IsAdult && CanUse(FIRE_ARROWS);}}),
|
||||
//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));}}),
|
||||
});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_MQ_SHARED] = Area("Spirit Temple MQ Shared", "Spirit Temple", 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) || IsAdult;}}),
|
||||
//Trick: CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT || IsAdult
|
||||
LocationAccess(SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, {[]{return IsAdult;}}),
|
||||
//Trick: (LogicSpiritMQSunBlockGS && Boomerange && (CanPlay(SongOfTime) || LogicSpiritMQSunBlockSoT)) || IsAdult
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, {[]{return (SmallKeys(SPIRIT_TEMPLE, 7) && (CanPlay(SongOfTime) || 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) || 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)
|
||||
});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_MQ_LOWER_ADULT] = Area("Spirit Temple MQ Lower Adult", "Spirit Temple", 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;}}),
|
||||
}, {});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_MQ_BOSS_AREA] = Area("Spirit Temple MQ Boss Area", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&SpiritTempleClear, {[]{return SpiritTempleClear || (MirrorShield && BossKeySpiritTemple);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, {[]{return LogicLensSpiritMQ || CanUse(LENS_OF_TRUTH);}}),
|
||||
LocationAccess(SPIRIT_TEMPLE_TWINROVA_HEART, {[]{return MirrorShield && BossKeySpiritTemple;}}),
|
||||
LocationAccess(TWINROVA, {[]{return MirrorShield && BossKeySpiritTemple;}}),
|
||||
}, {});
|
||||
|
||||
areaTable[SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND] = Area("Spirit Temple MQ Mirror Shield Hand", "Spirit Temple", SPIRIT_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, {[]{return true;}}),
|
||||
}, {});
|
||||
}
|
||||
}
|
@ -0,0 +1,351 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
#include "../dungeon.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_WaterTemple() {
|
||||
/*--------------------------
|
||||
| VANILLA/MQ DECIDER |
|
||||
---------------------------*/
|
||||
areaTable[WATER_TEMPLE_ENTRYWAY] = Area("Water Temple Entryway", "Water Temple", 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;}}),
|
||||
});
|
||||
|
||||
/*--------------------------
|
||||
| VANILLA DUNGEON |
|
||||
---------------------------*/
|
||||
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, {}, {}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_ENTRYWAY, {[]{return true;}}),
|
||||
Entrance(WATER_TEMPLE_EAST_LOWER, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(ZORA_TUNIC)) && (CanUse(IRON_BOOTS) || (CanUse(LONGSHOT) && LogicWaterTempleTorchLongshot)));},
|
||||
/*Glitched*/[]{return ((Bugs || Fish) && CanUse(HOVER_BOOTS) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::INTERMEDIATE)) || (CanUse(FARORES_WIND) &&
|
||||
((CanUse(NAYRUS_LOVE) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::NOVICE)) || (CanUseMagicArrow && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::ADVANCED))));}}),
|
||||
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));},
|
||||
/*Glitched*/[]{return CanUse(IRON_BOOTS) && (WaterTempleMiddle || WaterTempleHigh) && (LogicFewerTunicRequirements || CanUse(ZORA_TUNIC)) && AdultCanAccess(WATER_TEMPLE_WEST_LOWER) && CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
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;},
|
||||
/*Glitched*/[]{return WaterTempleLow && (CanDoGlitch(GlitchType::HammerSlide, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
Entrance(WATER_TEMPLE_HIGH_WATER, {[]{return IsAdult && (CanUse(HOVER_BOOTS) || (LogicWaterTempleUpperBoost && Bombs && CanTakeDamage));},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE) || (Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
Entrance(WATER_TEMPLE_BLOCK_CORRIDOR, {[]{return (WaterTempleLow || WaterTempleMiddle) && (CanUse(SLINGSHOT) || CanUse(BOW)) && (CanUse(LONGSHOT) || CanUse(HOVER_BOOTS) || (LogicWaterCentralBow && (IsAdult || WaterTempleMiddle)));},
|
||||
/*Glitched*/[]{return (WaterTempleLow || WaterTempleMiddle) && IsAdult && CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(WATER_TEMPLE_FALLING_PLATFORM_ROOM, {[]{return WaterTempleHigh && SmallKeys(WATER_TEMPLE, 4);},
|
||||
/*Glitched*/[]{return SmallKeys(WATER_TEMPLE, 4) && (CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HammerSlide, GlitchDifficulty::NOVICE));}}),
|
||||
Entrance(WATER_TEMPLE_PRE_BOSS_ROOM, {[]{return WaterTempleHigh && CanUse(LONGSHOT);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::HammerSlide, GlitchDifficulty::NOVICE) ||
|
||||
(Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_EAST_LOWER] = Area("Water Temple East Lower", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&WaterTempleLow, {[]{return WaterTempleLow || CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return ZeldasLullaby && (CanDoGlitch(GlitchType::DungeonBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield &&
|
||||
((Bombs && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || (HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)))));}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_LOBBY, {[]{return WaterTempleLow || ((LogicFewerTunicRequirements || CanUse(ZORA_TUNIC)) && CanUse(IRON_BOOTS));},
|
||||
/*Glitched*/[]{return ((Bugs || Fish) && CanUse(HOVER_BOOTS) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::INTERMEDIATE)) || (CanUse(FARORES_WIND) &&
|
||||
((CanUse(NAYRUS_LOVE) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::NOVICE)) || (CanUseMagicArrow && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::ADVANCED))));}}),
|
||||
Entrance(WATER_TEMPLE_MAP_ROOM, {[]{return WaterTempleHigh;}}),
|
||||
Entrance(WATER_TEMPLE_CRACKED_WALL, {[]{return WaterTempleMiddle || (WaterTempleHigh && WaterTempleLow && ((CanUse(HOVER_BOOTS) && LogicWaterCrackedWallHovers) || LogicWaterCrackedWallNothing));},
|
||||
/*Glitched*/[]{return WaterTempleHigh && WaterTempleLow && CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);}}),
|
||||
Entrance(WATER_TEMPLE_TORCH_ROOM, {[]{return WaterTempleLow && (HasFireSourceWithTorch || CanUse(BOW));}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_MAP_ROOM] = Area("Water Temple Map Room", "Water Temple", 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);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_EAST_LOWER, {[]{return (MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_CRACKED_WALL] = Area("Water Temple Cracked Wall", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_CRACKED_WALL_CHEST, {[]{return HasExplosives;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_EAST_LOWER, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_TORCH_ROOM] = Area("Water Temple Torch Room", "Water Temple", 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);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_EAST_LOWER, {[]{return (MagicMeter && CanUse(KOKIRI_SWORD)) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || CanUse(HOOKSHOT);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_NORTH_LOWER] = Area("Water Temple North Lower", "Water Temple", 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);},
|
||||
/*Glitched*/[]{return ((Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)) ||
|
||||
CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE)) && SmallKeys(WATER_TEMPLE, 4);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_BOULDERS_LOWER] = Area("Water Temple Boulders Lower", "Water Temple", 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));});}}),
|
||||
}, {
|
||||
//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));}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_BLOCK_ROOM] = Area("Water Temple Block Room", "Water Temple", 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));},
|
||||
/*Glitched*/[]{return CanUse(HOOKSHOT) && CanDoGlitch(GlitchType::Megaflip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_JETS_ROOM] = Area("Water Temple Jets Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_BLOCK_ROOM, {[]{return CanUse(HOOKSHOT);}}),
|
||||
Entrance(WATER_TEMPLE_BOULDERS_UPPER, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_BOULDERS_UPPER] = Area("Water Temple Boulders Upper", "Water Temple", 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);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_BOSS_KEY_ROOM] = Area("Water Temple Boss Key Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return true;}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(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);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_SOUTH_LOWER] = Area("Water Temple South Lower", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_GS_BEHIND_GATE, {[]{return CanUse(HOOKSHOT) || (IsAdult && CanUse(HOVER_BOOTS));},
|
||||
/*Glitched*/[]{return (CanUse(BOOMERANG) && CanDoGlitch(GlitchType::HoverBoost, GlitchDifficulty::INTERMEDIATE)) ||
|
||||
(Bombs && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_LOBBY, {[]{return CanUse(IRON_BOOTS);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_WEST_LOWER] = Area("Water Temple West Lower", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_LOBBY, {[]{return CanUse(HOOKSHOT) && CanUse(IRON_BOOTS) && GoronBracelet;},
|
||||
/*Glitched*/[]{return CanUse(IRON_BOOTS) && (LogicFewerTunicRequirements || CanUse(ZORA_TUNIC)) && CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_DRAGON_CHEST, {[]{return (CanUse(HOOKSHOT) && CanUse(IRON_BOOTS)) || (IsAdult && LogicWaterDragonAdult && HasBombchus && (CanDive || CanUse(IRON_BOOTS))) ||
|
||||
Here(WATER_TEMPLE_RIVER, []{return IsAdult && CanUse(BOW) && ((LogicWaterDragonAdult && (CanDive || CanUse(IRON_BOOTS))) || LogicWaterDragonJumpDive);});},
|
||||
/*Glitched*/[]{return Bombs && ((IsAdult && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::ADVANCED)) || (CanUse(IRON_BOOTS) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE)));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {}, {
|
||||
//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;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::NOVICE) && CanUse(IRON_BOOTS) && WaterTimer >= 40;}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_CENTRAL_PILLAR_UPPER] = Area("Water Temple Central Pillar Upper", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&WaterTempleMiddle, {[]{return WaterTempleMiddle || CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return ZeldasLullaby && (CanDoGlitch(GlitchType::DungeonBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield &&
|
||||
(CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) || (HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)))));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_GS_CENTRAL_PILLAR, {[]{return CanUse(LONGSHOT) || (LogicWaterCentralGSFW && WaterTempleHigh && CanUse(FARORES_WIND) && HookshotOrBoomerang);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_LOBBY, {[]{return true;}}),
|
||||
Entrance(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, {}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_CENTRAL_PILLAR_CHEST, {[]{return CanUse(HOOKSHOT) && CanUse(IRON_BOOTS) && WaterTimer >= 40;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_CENTRAL_PILLAR_LOWER, {[]{return CanUse(IRON_BOOTS) && WaterTimer >= 16;}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_EAST_MIDDLE] = Area("Water Temple East Middle", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_COMPASS_CHEST, {[]{return CanUseProjectile;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_LOBBY, {[]{return CanUse(IRON_BOOTS);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_WEST_MIDDLE] = Area("Water Temple West Middle", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_LOBBY, {[]{return true;}}),
|
||||
Entrance(WATER_TEMPLE_HIGH_WATER, {[]{return CanUseProjectile;}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_HIGH_WATER] = Area("Water Temple High Water", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&WaterTempleHigh, {[]{return WaterTempleHigh || CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return ZeldasLullaby && (CanDoGlitch(GlitchType::DungeonBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield &&
|
||||
(CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) || (HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)))));}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_LOBBY, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_BLOCK_CORRIDOR] = Area("Water Temple Block Corridor", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_CENTRAL_BOW_TARGET_CHEST, {[]{return GoronBracelet && (WaterTempleLow || WaterTempleMiddle);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::INTERMEDIATE) && (WaterTempleLow || WaterTempleMiddle);}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_LOBBY, {[]{return CanUse(HOOKSHOT);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_FALLING_PLATFORM_ROOM] = Area("Water Temple Falling Platform Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM, {[]{return CanUse(LONGSHOT) || (LogicWaterFallingPlatformGS && IsAdult && HookshotOrBoomerang);}}),
|
||||
}, {
|
||||
//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);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_DRAGON_PILLARS_ROOM] = Area("Water Temple Dragon Pillars Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_FALLING_PLATFORM_ROOM, {[]{return CanUseProjectile;}}),
|
||||
Entrance(WATER_TEMPLE_DARK_LINK_ROOM, {[]{return CanUse(HOOKSHOT);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_DARK_LINK_ROOM] = Area("Water Temple Dark Link Room", "Water Temple", 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);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_LONGSHOT_ROOM] = Area("Water Temple Longshot Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_LONGSHOT_CHEST, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_DARK_LINK_ROOM, {[]{return true;}}),
|
||||
Entrance(WATER_TEMPLE_RIVER, {[]{return IsChild || CanPlay(SongOfTime);},
|
||||
/*Glitched*/[]{return SongOfTime && (CanDoGlitch(GlitchType::DungeonBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield &&
|
||||
(CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED) || (HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED)))));}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_RIVER] = Area("Water Temple River", "Water Temple", 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));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_DRAGON_ROOM, {[]{return (CanUse(SLINGSHOT) || CanUse(BOW)) && (IsAdult || CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT));}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_PRE_BOSS_ROOM] = Area("Water Temple Pre Boss Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FairyPot, {[]{return true;}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_LOBBY, {[]{return true;}}),
|
||||
Entrance(WATER_TEMPLE_BOSS_ROOM, {[]{return BossKeyWaterTemple;}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_BOSS_ROOM] = Area("Water Temple Boss Room", "Water Temple", WATER_TEMPLE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&WaterTempleClear, {[]{return WaterTempleClear || (CanUse(HOOKSHOT) && (CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD)));}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_MORPHA_HEART, {[]{return WaterTempleClear;}}),
|
||||
LocationAccess(MORPHA, {[]{return WaterTempleClear;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_ENTRYWAY, {[]{return WaterTempleClear;}}),
|
||||
});
|
||||
}
|
||||
|
||||
/*---------------------------
|
||||
| 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, {
|
||||
//Events
|
||||
EventAccess(&WaterTempleClear, {[]{return BossKeyWaterTemple && IsAdult && CanUse(LONGSHOT);}}),
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(WATER_TEMPLE_MORPHA_HEART, {[]{return BossKeyWaterTemple && IsAdult && CanUse(LONGSHOT);}}),
|
||||
LocationAccess(MORPHA, {[]{return BossKeyWaterTemple && IsAdult && CanUse(LONGSHOT);}}),
|
||||
}, {
|
||||
//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);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_MQ_DIVE] = Area("Water Temple MQ Dive", "Water Temple", 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) && (CanUse(DINS_FIRE) && CanPlay(SongOfTime));}}),
|
||||
//Trick: IsAdult && CanUse(ZORA_TUNIC) && CanUse(HOOKSHOT) && ((LogicWaterMQCentralPillar && CanUse(FIRE_ARROWS)) || (CanUse(DINS_FIRE) && CanPlay(SongOfTime)))
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(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, {}, {
|
||||
//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);}}),
|
||||
}, {});
|
||||
|
||||
areaTable[WATER_TEMPLE_MQ_DARK_LINK_REGION] = Area("Water Temple MQ Dark Link Region", "Water Temple", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS, {[]{return IsAdult && WaterTimer >= 24 && CanUse(DINS_FIRE) && CanUse(IRON_BOOTS);}}),
|
||||
});
|
||||
|
||||
areaTable[WATER_TEMPLE_MQ_BASEMENT_GATED_AREAS] = Area("Water Temple MQ Basement Gated Areas", "Water Temple", 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 SmallKeys(WATER_TEMPLE, 2) && (HoverBoots || CanUse(SCARECROW) || LogicWaterNorthBasementLedgeJump);}}),
|
||||
//Trick: LogicWaterMQLockedGS || (SmallKeys(WATER_TEMPLE, 2) && (HoverBoots || CanUse(SCARECROW) || LogicWaterNorthBasementLedgeJump))
|
||||
}, {});
|
||||
}
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
#include "../location_access.hpp"
|
||||
#include "../logic.hpp"
|
||||
#include "../entrance.hpp"
|
||||
|
||||
using namespace Logic;
|
||||
using namespace Settings;
|
||||
|
||||
void AreaTable_Init_ZorasDomain() {
|
||||
areaTable[ZR_FRONT] = Area("ZR Front", "Zora River", ZORAS_RIVER, DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(ZR_GS_TREE, {[]{return IsChild && CanChildAttack;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(ZORAS_RIVER, {[]{return IsAdult || CanBlastOrSmash;},
|
||||
/*Glitched*/[]{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);}}),
|
||||
Entrance(HYRULE_FIELD, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[ZORAS_RIVER] = Area("Zora River", "Zora River", 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(&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);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && ZeldasLullaby && SariasSong && SunsSong && EponasSong && SongOfTime && SongOfStorms;}}),
|
||||
LocationAccess(ZR_FROGS_IN_THE_RAIN, {[]{return IsChild && CanPlay(SongOfStorms);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && SongOfStorms;}}),
|
||||
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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(ZR_FRONT, {[]{return true;}}),
|
||||
Entrance(ZR_OPEN_GROTTO, {[]{return true;}}),
|
||||
Entrance(ZR_FAIRY_GROTTO, {[]{return Here(ZORAS_RIVER, []{return CanBlastOrSmash;});},
|
||||
/*Glitched*/[]{return Here(ZORAS_RIVER, []{return CanUse(STICKS) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED);});}}),
|
||||
Entrance(THE_LOST_WOODS, {[]{return CanDive || CanUse(IRON_BOOTS);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::INTERMEDIATE) || (CanUse(FARORES_WIND) && (FaroresWindAnywhere || (CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && (HasBottle || (IsAdult && (HasBoots || ClaimCheck)) || (IsChild && WeirdEgg)))) &&
|
||||
((CanUse(NAYRUS_LOVE) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::NOVICE)) || (CanUseMagicArrow && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::ADVANCED))));}}),
|
||||
Entrance(ZR_STORMS_GROTTO, {[]{return CanOpenStormGrotto;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
||||
Entrance(ZR_BEHIND_WATERFALL, {[]{return CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::HookshotJump_Boots, GlitchDifficulty::ADVANCED) || ((CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) ||
|
||||
((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby);}}),
|
||||
});
|
||||
|
||||
areaTable[ZR_BEHIND_WATERFALL] = Area("ZR Behind Waterfall", "Zora River", NONE, DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(ZORAS_RIVER, {[]{return true;}}),
|
||||
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[ZR_OPEN_GROTTO] = Area("ZR Open Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, grottoEvents, {
|
||||
//Locations
|
||||
LocationAccess(ZR_OPEN_GROTTO_CHEST, {[]{return true;}}),
|
||||
LocationAccess(ZR_OPEN_GROTTO_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(ZORAS_RIVER, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[ZR_FAIRY_GROTTO] = Area("ZR Fairy Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Event
|
||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(ZORAS_RIVER, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[ZR_STORMS_GROTTO] = Area("ZR Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(ZR_DEKU_SCRUB_GROTTO_REAR, {[]{return CanStunDeku;}}),
|
||||
LocationAccess(ZR_DEKU_SCRUB_GROTTO_FRONT, {[]{return CanStunDeku;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(ZORAS_RIVER, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[ZORAS_DOMAIN] = Area("Zoras Domain", "Zoras Domain", ZORAS_DOMAIN, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&EyeballFrogAccess, {[]{return EyeballFrogAccess || (IsAdult && KingZoraThawed && (Eyedrops || EyeballFrog || Prescription || PrescriptionAccess));}}),
|
||||
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
|
||||
EventAccess(&NutPot, {[]{return true;}}),
|
||||
EventAccess(&StickPot, {[]{return StickPot || IsChild;}}),
|
||||
EventAccess(&FishGroup, {[]{return FishGroup || IsChild;}}),
|
||||
EventAccess(&KingZoraThawed, {[]{return KingZoraThawed || (IsAdult && BlueFire);}}),
|
||||
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) && CanGetNightTimeGS;}}),
|
||||
LocationAccess(ZD_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(ZR_BEHIND_WATERFALL, {[]{return true;}}),
|
||||
Entrance(LAKE_HYLIA, {[]{return IsChild && (CanDive || CanUse(IRON_BOOTS));},
|
||||
/*Glitched*/[]{return (IsAdult && GlitchZDOoBJumpSlash) || (IsChild && CanUse(FARORES_WIND) && (FaroresWindAnywhere || (CanDoGlitch(GlitchType::RestrictedItems, GlitchDifficulty::NOVICE) && (HasBottle || WeirdEgg))) &&
|
||||
((CanUse(NAYRUS_LOVE) && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::NOVICE)) || (CanUseMagicArrow && CanDoGlitch(GlitchType::CutsceneDive, GlitchDifficulty::ADVANCED))));}}),
|
||||
Entrance(ZD_BEHIND_KING_ZORA, {[]{return DeliverLetter || ZorasFountain.Is(ZORASFOUNTAIN_OPEN) || (ZorasFountain.Is(ZORASFOUNTAIN_ADULT) && IsAdult);},
|
||||
/*Glitched*/[]{return ((IsChild || CanUse(IRON_BOOTS)) && CanDoGlitch(GlitchType::TripleSlashClip, GlitchDifficulty::NOVICE)) || CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::NOVICE) ||
|
||||
CanDoGlitch(GlitchType::LedgeCancel, GlitchDifficulty::NOVICE) || CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) || CanDoGlitch(GlitchType::LedgeClip, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(ZD_SHOP, {[]{return IsChild || BlueFire;},
|
||||
/*Glitched*/[]{return GlitchZDOoBJumpSlash.Value<bool>();}}),
|
||||
Entrance(ZD_STORMS_GROTTO, {[]{return CanOpenStormGrotto;},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && SongOfStorms && (ShardOfAgony || LogicGrottosWithoutAgony);}}),
|
||||
});
|
||||
|
||||
areaTable[ZD_BEHIND_KING_ZORA] = Area("ZD Behind King Zora", "Zoras Domain", NONE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(ZORAS_DOMAIN, {[]{return DeliverLetter || ZorasFountain.Is(ZORASFOUNTAIN_OPEN) || (ZorasFountain.Is(ZORASFOUNTAIN_ADULT) && IsAdult);},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::ASlide, GlitchDifficulty::NOVICE) || (CanUse(LONGSHOT) && CanDoGlitch(GlitchType::HookshotClip, GlitchDifficulty::NOVICE)) || (Bombs && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE) && CanDoGlitch(GlitchType::ISG, GlitchDifficulty::INTERMEDIATE));}}),
|
||||
Entrance(ZORAS_FOUNTAIN, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[ZD_SHOP] = Area("ZD Shop", "", 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;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[ZD_STORMS_GROTTO] = Area("ZD Storms Grotto", "", NONE, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&FreeFairies, {[]{return true;}}),
|
||||
}, {}, {
|
||||
//Exits
|
||||
Entrance(ZORAS_DOMAIN, {[]{return true;}}),
|
||||
});
|
||||
|
||||
areaTable[ZORAS_FOUNTAIN] = Area("Zoras Fountain", "Zoras Fountain", ZORAS_FOUNTAIN, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&GossipStoneFairy, {[]{return GossipStoneFairy || CanSummonGossipFairyWithoutSuns;}}),
|
||||
EventAccess(&ButterflyFairy, {[]{return ButterflyFairy || (CanUse(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;},
|
||||
/*Glitched*/[]{return IsChild && AtNight && CanGetNightTimeGS && HasBombchus && CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::NOVICE);}}),
|
||||
LocationAccess(ZF_GS_HIDDEN_CAVE, {[]{return CanUse(SILVER_GAUNTLETS) && CanBlastOrSmash && HookshotOrBoomerang && IsAdult && AtNight && CanGetNightTimeGS;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::LedgeCancel, GlitchDifficulty::INTERMEDIATE) && IsAdult && HookshotOrBoomerang && AtNight && CanGetNightTimeGS;}}),
|
||||
LocationAccess(ZF_FAIRY_GOSSIP_STONE, {[]{return true;}}),
|
||||
LocationAccess(ZF_JABU_GOSSIP_STONE, {[]{return true;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(ZD_BEHIND_KING_ZORA, {[]{return true;}}),
|
||||
Entrance(JABU_JABUS_BELLY_ENTRYWAY, {[]{return (IsChild && Fish);},
|
||||
/*Glitched*/[]{return (IsChild && CanUse(STICKS) && GlitchJabuStickRecoil) || (IsAdult && GlitchJabuAdult);}}),
|
||||
Entrance(ICE_CAVERN_ENTRYWAY, {[]{return IsAdult;},
|
||||
/*Glitched*/[]{return CanDoGlitch(GlitchType::BombHover, GlitchDifficulty::INTERMEDIATE);}}),
|
||||
Entrance(ZF_GREAT_FAIRY_FOUNTAIN, {[]{return HasExplosives || (CanUse(SILVER_GAUNTLETS) && Hammer && LogicZFGreatFairy);},
|
||||
/*Glitched*/[]{return IsChild && (KokiriSword || Sticks) && CanShield && (CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::ADVANCED) || (CanDoGlitch(GlitchType::ISG, GlitchDifficulty::NOVICE) && CanDoGlitch(GlitchType::SeamWalk, GlitchDifficulty::INTERMEDIATE)));}}),
|
||||
});
|
||||
|
||||
areaTable[ZF_GREAT_FAIRY_FOUNTAIN] = Area("ZF Great Fairy Fountain", "", NONE, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LocationAccess(ZF_GREAT_FAIRY_REWARD, {[]{return CanPlay(ZeldasLullaby);},
|
||||
/*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::INTERMEDIATE) || ((Bugs || Fish) && CanShield && (CanSurviveDamage || (Fairy && NumBottles >= 2)) && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) ||
|
||||
((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && ZeldasLullaby;}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(ZORAS_FOUNTAIN, {[]{return true;}}),
|
||||
});
|
||||
}
|
1218
soh/soh/Enhancements/randomizer/3drando/logic.cpp
Normal file
1218
soh/soh/Enhancements/randomizer/3drando/logic.cpp
Normal file
File diff suppressed because it is too large
Load Diff
387
soh/soh/Enhancements/randomizer/3drando/logic.hpp
Normal file
387
soh/soh/Enhancements/randomizer/3drando/logic.hpp
Normal file
@ -0,0 +1,387 @@
|
||||
#pragma once
|
||||
|
||||
#include "keys.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace Logic {
|
||||
extern bool noVariable;
|
||||
|
||||
// Child item logic
|
||||
extern bool KokiriSword;
|
||||
extern bool Slingshot;
|
||||
extern bool ZeldasLetter;
|
||||
extern bool WeirdEgg;
|
||||
extern bool HasBottle;
|
||||
extern bool BombBag;
|
||||
extern bool Bombchus;
|
||||
extern bool Bombchus5;
|
||||
extern bool Bombchus10;
|
||||
extern bool Bombchus20;
|
||||
extern bool MagicBean;
|
||||
extern bool MagicBeanPack;
|
||||
extern bool RutosLetter;
|
||||
extern bool Boomerang;
|
||||
extern bool DinsFire;
|
||||
extern bool FaroresWind;
|
||||
extern bool NayrusLove;
|
||||
extern bool LensOfTruth;
|
||||
extern bool ShardOfAgony;
|
||||
extern bool SkullMask;
|
||||
extern bool MaskOfTruth;
|
||||
|
||||
// Adult logic
|
||||
extern bool Bow;
|
||||
extern bool Hammer;
|
||||
extern bool IronBoots;
|
||||
extern bool HoverBoots;
|
||||
extern bool MirrorShield;
|
||||
extern bool GoronTunic;
|
||||
extern bool ZoraTunic;
|
||||
extern bool Epona;
|
||||
extern bool BigPoe;
|
||||
extern bool GerudoToken;
|
||||
extern bool FireArrows;
|
||||
extern bool IceArrows;
|
||||
extern bool LightArrows;
|
||||
extern bool MasterSword;
|
||||
extern bool BiggoronSword;
|
||||
|
||||
// Trade Quest
|
||||
extern bool PocketEgg;
|
||||
extern bool Cojiro;
|
||||
extern bool OddMushroom;
|
||||
extern bool OddPoultice;
|
||||
extern bool PoachersSaw;
|
||||
extern bool BrokenSword;
|
||||
extern bool Prescription;
|
||||
extern bool EyeballFrog;
|
||||
extern bool Eyedrops;
|
||||
extern bool ClaimCheck;
|
||||
|
||||
// Trade Quest Events
|
||||
extern bool WakeUpAdultTalon;
|
||||
extern bool CojiroAccess;
|
||||
extern bool OddMushroomAccess;
|
||||
extern bool OddPoulticeAccess;
|
||||
extern bool PoachersSawAccess;
|
||||
extern bool BrokenSwordAccess;
|
||||
extern bool PrescriptionAccess;
|
||||
extern bool EyeballFrogAccess;
|
||||
extern bool EyedropsAccess;
|
||||
extern bool DisableTradeRevert;
|
||||
|
||||
// Songs
|
||||
extern bool ZeldasLullaby;
|
||||
extern bool SariasSong;
|
||||
extern bool SunsSong;
|
||||
extern bool SongOfStorms;
|
||||
extern bool EponasSong;
|
||||
extern bool SongOfTime;
|
||||
extern bool MinuetOfForest;
|
||||
extern bool BoleroOfFire;
|
||||
extern bool SerenadeOfWater;
|
||||
extern bool RequiemOfSpirit;
|
||||
extern bool NocturneOfShadow;
|
||||
extern bool PreludeOfLight;
|
||||
|
||||
// Stones and Meddallions
|
||||
extern bool ForestMedallion;
|
||||
extern bool FireMedallion;
|
||||
extern bool WaterMedallion;
|
||||
extern bool SpiritMedallion;
|
||||
extern bool ShadowMedallion;
|
||||
extern bool LightMedallion;
|
||||
extern bool KokiriEmerald;
|
||||
extern bool GoronRuby;
|
||||
extern bool ZoraSapphire;
|
||||
|
||||
// Dungeon Clears
|
||||
extern bool DekuTreeClear;
|
||||
extern bool DodongosCavernClear;
|
||||
extern bool JabuJabusBellyClear;
|
||||
extern bool ForestTempleClear;
|
||||
extern bool FireTempleClear;
|
||||
extern bool WaterTempleClear;
|
||||
extern bool SpiritTempleClear;
|
||||
extern bool ShadowTempleClear;
|
||||
|
||||
// Trial Clears
|
||||
extern bool ForestTrialClear;
|
||||
extern bool FireTrialClear;
|
||||
extern bool WaterTrialClear;
|
||||
extern bool SpiritTrialClear;
|
||||
extern bool ShadowTrialClear;
|
||||
extern bool LightTrialClear;
|
||||
|
||||
// Progression Items
|
||||
extern uint8_t ProgressiveBulletBag;
|
||||
extern uint8_t ProgressiveBombBag;
|
||||
extern uint8_t ProgressiveScale;
|
||||
extern uint8_t ProgressiveHookshot;
|
||||
extern uint8_t ProgressiveBow;
|
||||
extern uint8_t ProgressiveStrength;
|
||||
extern uint8_t ProgressiveWallet;
|
||||
extern uint8_t ProgressiveMagic;
|
||||
extern uint8_t ProgressiveOcarina;
|
||||
extern uint8_t ProgressiveGiantKnife;
|
||||
|
||||
// Keysanity
|
||||
extern bool IsKeysanity;
|
||||
|
||||
// Keys
|
||||
extern uint8_t ForestTempleKeys;
|
||||
extern uint8_t FireTempleKeys;
|
||||
extern uint8_t WaterTempleKeys;
|
||||
extern uint8_t SpiritTempleKeys;
|
||||
extern uint8_t ShadowTempleKeys;
|
||||
extern uint8_t BottomOfTheWellKeys;
|
||||
extern uint8_t GerudoTrainingGroundsKeys;
|
||||
extern uint8_t GerudoFortressKeys;
|
||||
extern uint8_t GanonsCastleKeys;
|
||||
extern uint8_t TreasureGameKeys;
|
||||
|
||||
// Boss Keys
|
||||
extern bool BossKeyForestTemple;
|
||||
extern bool BossKeyFireTemple;
|
||||
extern bool BossKeyWaterTemple;
|
||||
extern bool BossKeySpiritTemple;
|
||||
extern bool BossKeyShadowTemple;
|
||||
extern bool BossKeyGanonsCastle;
|
||||
|
||||
// Gold Skulltula Count
|
||||
extern uint8_t GoldSkulltulaTokens;
|
||||
|
||||
// Bottle Count, with and without Ruto's Letter
|
||||
extern uint8_t Bottles;
|
||||
extern uint8_t NumBottles;
|
||||
extern bool NoBottles;
|
||||
|
||||
// item and bottle drops
|
||||
extern bool DekuNutDrop;
|
||||
extern bool NutPot;
|
||||
extern bool NutCrate;
|
||||
extern bool DekuBabaNuts;
|
||||
extern bool DekuStickDrop;
|
||||
extern bool StickPot;
|
||||
extern bool DekuBabaSticks;
|
||||
extern bool BugsAccess;
|
||||
extern bool BugShrub;
|
||||
extern bool WanderingBugs;
|
||||
extern bool BugRock;
|
||||
extern bool BlueFireAccess;
|
||||
extern bool FishAccess;
|
||||
extern bool FishGroup;
|
||||
extern bool LoneFish;
|
||||
extern bool FairyAccess;
|
||||
extern bool GossipStoneFairy;
|
||||
extern bool BeanPlantFairy;
|
||||
extern bool ButterflyFairy;
|
||||
extern bool FairyPot;
|
||||
extern bool FreeFairies;
|
||||
extern bool FairyPond;
|
||||
extern bool BombchuDrop;
|
||||
|
||||
extern bool BuyBombchus5;
|
||||
extern bool BuyBombchus10;
|
||||
extern bool BuyBombchus20;
|
||||
extern bool BuyArrow;
|
||||
extern bool BuyBomb;
|
||||
extern bool BuyGPotion;
|
||||
extern bool BuyBPotion;
|
||||
extern bool BuySeed;
|
||||
extern bool MagicRefill;
|
||||
|
||||
extern uint8_t PieceOfHeart;
|
||||
extern uint8_t HeartContainer;
|
||||
extern bool DoubleDefense;
|
||||
|
||||
/* --- HELPERS --- */
|
||||
/* These are used to simplify reading the logic, but need to be updated
|
||||
/ every time a base value is updated. */
|
||||
|
||||
extern bool Ocarina;
|
||||
extern bool OcarinaOfTime;
|
||||
extern bool MagicMeter;
|
||||
extern bool Hookshot;
|
||||
extern bool Longshot;
|
||||
extern bool GoronBracelet;
|
||||
extern bool SilverGauntlets;
|
||||
extern bool GoldenGauntlets;
|
||||
extern bool SilverScale;
|
||||
extern bool GoldScale;
|
||||
extern bool AdultsWallet;
|
||||
|
||||
extern bool ChildScarecrow;
|
||||
extern bool AdultScarecrow;
|
||||
extern bool ScarecrowSong;
|
||||
extern bool Scarecrow;
|
||||
extern bool DistantScarecrow;
|
||||
|
||||
extern bool Bombs;
|
||||
extern bool DekuShield;
|
||||
extern bool HylianShield;
|
||||
extern bool Nuts;
|
||||
extern bool Sticks;
|
||||
extern bool Bugs;
|
||||
extern bool BlueFire;
|
||||
extern bool Fish;
|
||||
extern bool Fairy;
|
||||
extern bool BottleWithBigPoe;
|
||||
|
||||
extern bool Bombs;
|
||||
extern bool FoundBombchus;
|
||||
extern bool CanPlayBowling;
|
||||
extern bool HasBombchus;
|
||||
extern bool HasExplosives;
|
||||
extern bool HasBoots;
|
||||
extern bool IsChild;
|
||||
extern bool IsAdult;
|
||||
extern bool IsGlitched;
|
||||
extern bool CanBlastOrSmash;
|
||||
extern bool CanChildAttack;
|
||||
extern bool CanChildDamage;
|
||||
extern bool CanCutShrubs;
|
||||
extern bool CanDive;
|
||||
extern bool CanLeaveForest;
|
||||
extern bool CanPlantBugs;
|
||||
extern bool CanRideEpona;
|
||||
extern bool CanStunDeku;
|
||||
extern bool CanSummonGossipFairy;
|
||||
extern bool CanSummonGossipFairyWithoutSuns;
|
||||
extern bool NeedNayrusLove;
|
||||
extern bool CanSurviveDamage;
|
||||
extern bool CanTakeDamage;
|
||||
extern bool CanTakeDamageTwice;
|
||||
// extern bool CanPlantBean;
|
||||
extern bool CanOpenBombGrotto;
|
||||
extern bool CanOpenStormGrotto;
|
||||
extern bool HookshotOrBoomerang;
|
||||
extern bool CanGetNightTimeGS;
|
||||
extern bool BigPoeKill;
|
||||
|
||||
extern uint8_t BaseHearts;
|
||||
extern uint8_t Hearts;
|
||||
extern uint8_t Multiplier;
|
||||
extern uint8_t EffectiveHealth;
|
||||
extern uint8_t FireTimer;
|
||||
extern uint8_t WaterTimer;
|
||||
|
||||
extern bool GuaranteeTradePath;
|
||||
extern bool GuaranteeHint;
|
||||
extern bool HasFireSource;
|
||||
extern bool HasFireSourceWithTorch;
|
||||
|
||||
// Gerudo Fortress
|
||||
extern bool CanFinishGerudoFortress;
|
||||
|
||||
extern bool HasShield;
|
||||
extern bool CanShield;
|
||||
extern bool CanJumpslash;
|
||||
extern bool CanUseProjectile;
|
||||
extern bool CanUseMagicArrow;
|
||||
|
||||
// Bridge Requirements
|
||||
extern bool HasAllStones;
|
||||
extern bool HasAllMedallions;
|
||||
extern bool CanBuildRainbowBridge;
|
||||
extern bool CanTriggerLACS;
|
||||
|
||||
// Other
|
||||
extern bool AtDay;
|
||||
extern bool AtNight;
|
||||
extern bool LinksCow;
|
||||
extern uint8_t Age;
|
||||
|
||||
// Events
|
||||
extern bool ShowedMidoSwordAndShield;
|
||||
extern bool CarpenterRescue;
|
||||
extern bool DampesWindmillAccess;
|
||||
extern bool GF_GateOpen;
|
||||
extern bool GtG_GateOpen;
|
||||
extern bool DrainWell;
|
||||
extern bool GoronCityChildFire;
|
||||
extern bool GCWoodsWarpOpen;
|
||||
extern bool GCDaruniasDoorOpenChild;
|
||||
extern bool StopGCRollingGoronAsAdult;
|
||||
extern bool WaterTempleLow;
|
||||
extern bool WaterTempleMiddle;
|
||||
extern bool WaterTempleHigh;
|
||||
extern bool KingZoraThawed;
|
||||
extern bool AtDampeTime;
|
||||
extern bool DeliverLetter;
|
||||
extern bool KakarikoVillageGateOpen;
|
||||
extern bool ForestTempleJoelle;
|
||||
extern bool ForestTempleBeth;
|
||||
extern bool ForestTempleJoAndBeth;
|
||||
extern bool ForestTempleAmy;
|
||||
extern bool ForestTempleMeg;
|
||||
extern bool ForestTempleAmyAndMeg;
|
||||
extern bool FireLoopSwitch;
|
||||
extern bool TimeTravel;
|
||||
|
||||
/* --- END OF HELPERS --- */
|
||||
|
||||
extern uint8_t AddedProgressiveBulletBags;
|
||||
extern uint8_t AddedProgressiveBombBags;
|
||||
extern uint8_t AddedProgressiveMagics;
|
||||
extern uint8_t AddedProgressiveScales;
|
||||
extern uint8_t AddedProgressiveHookshots;
|
||||
extern uint8_t AddedProgressiveBows;
|
||||
extern uint8_t AddedProgressiveWallets;
|
||||
extern uint8_t AddedProgressiveStrengths;
|
||||
extern uint8_t AddedProgressiveOcarinas;
|
||||
extern uint8_t TokensInPool;
|
||||
|
||||
enum class HasProjectileAge {
|
||||
Adult,
|
||||
Child,
|
||||
Both,
|
||||
Either,
|
||||
};
|
||||
|
||||
enum class GlitchType {
|
||||
RestrictedItems,
|
||||
SuperStab,
|
||||
ISG,
|
||||
BombHover,
|
||||
BombOI,
|
||||
OutdoorBombOI,
|
||||
WindmillBombOI,
|
||||
IndoorBombOI,
|
||||
DungeonBombOI,
|
||||
HoverBoost,
|
||||
SuperSlide,
|
||||
Megaflip,
|
||||
ASlide,
|
||||
HammerSlide,
|
||||
LedgeCancel,
|
||||
ActionSwap,
|
||||
QPA,
|
||||
HookshotClip,
|
||||
HookshotJump_Bonk,
|
||||
HookshotJump_Boots,
|
||||
CutsceneDive,
|
||||
NaviDive_Stick,
|
||||
TripleSlashClip,
|
||||
LedgeClip,
|
||||
SeamWalk,
|
||||
};
|
||||
|
||||
enum class GlitchDifficulty {
|
||||
NOVICE = 1,
|
||||
INTERMEDIATE,
|
||||
ADVANCED,
|
||||
EXPERT,
|
||||
HERO,
|
||||
};
|
||||
|
||||
void UpdateHelpers();
|
||||
bool CanPlay(bool song);
|
||||
bool CanUse(uint32_t itemName);
|
||||
bool HasProjectile(HasProjectileAge age);
|
||||
bool SmallKeys(Key dungeon, uint8_t requiredAmount);
|
||||
bool SmallKeys(Key dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched);
|
||||
bool CanDoGlitch(GlitchType glitch, GlitchDifficulty difficulty);
|
||||
bool EventsUpdated();
|
||||
void LogicReset();
|
||||
} // namespace Logic
|
550
soh/soh/Enhancements/randomizer/3drando/menu.cpp
Normal file
550
soh/soh/Enhancements/randomizer/3drando/menu.cpp
Normal file
@ -0,0 +1,550 @@
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
|
||||
#include "cosmetics.hpp"
|
||||
#include "menu.hpp"
|
||||
#include "patch.hpp"
|
||||
#include "preset.hpp"
|
||||
#include "randomizer.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "location_access.hpp"
|
||||
#include "debug.hpp"
|
||||
#include <Lib/spdlog/include/spdlog/spdlog.h>
|
||||
#include "randomizerTypes.h"
|
||||
|
||||
namespace {
|
||||
bool seedChanged;
|
||||
uint16_t pastSeedLength;
|
||||
std::vector<std::string> presetEntries;
|
||||
std::vector<Menu*> menuList;
|
||||
Option* currentSetting;
|
||||
Menu* currentMenu;
|
||||
} // namespace
|
||||
|
||||
void PrintTopScreen() {
|
||||
SPDLOG_INFO("\x1b[2;11H%sOcarina of Time 3D Randomizer%s", CYAN, RESET);
|
||||
SPDLOG_INFO("\x1b[3;18H%s%s-%s%s", CYAN, RANDOMIZER_VERSION, COMMIT_NUMBER, RESET);
|
||||
SPDLOG_INFO("\x1b[4;10HA/B/D-pad: Navigate Menu\n");
|
||||
SPDLOG_INFO(" Select: Exit to Homebrew Menu\n");
|
||||
SPDLOG_INFO(" Y: New Random Seed\n");
|
||||
SPDLOG_INFO(" X: Input Custom Seed\n");
|
||||
SPDLOG_INFO("\x1b[11;7HCurrent Seed: %s", Settings::seed.c_str());
|
||||
}
|
||||
|
||||
void MenuInit() {
|
||||
Settings::InitSettings();
|
||||
|
||||
seedChanged = false;
|
||||
pastSeedLength = Settings::seed.length();
|
||||
|
||||
Menu* main = new Menu("Main", MenuType::MainMenu, &Settings::mainMenu, MAIN_MENU);
|
||||
menuList.push_back(main);
|
||||
currentMenu = main;
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
if (!CreatePresetDirectories()) {
|
||||
printf("\x1b[20;5Failed to create preset directories.");
|
||||
printf("\x1b[21;5Loading presets might crash.");
|
||||
}
|
||||
|
||||
// If cached presets exist, load them
|
||||
LoadCachedSettings();
|
||||
LoadCachedCosmetics();
|
||||
// If Randomize all settings in a category is selected
|
||||
// Re-randomize them
|
||||
Settings::RandomizeAllSettings();
|
||||
|
||||
PrintTopScreen();
|
||||
|
||||
PrintMainMenu();
|
||||
}
|
||||
|
||||
#define KEY_DUP 0
|
||||
#define KEY_DDOWN 1
|
||||
#define KEY_DLEFT 2
|
||||
#define KEY_DRIGHT 3
|
||||
#define KEY_A 4
|
||||
#define KEY_B 5
|
||||
#define KEY_Y 6
|
||||
#define KEY_X 7
|
||||
|
||||
void MoveCursor(uint32_t kDown, bool updatedByHeld) {
|
||||
// Option sub menus need special checking for locked options
|
||||
if (currentMenu->mode == OPTION_SUB_MENU) {
|
||||
// Cancel if holding and reached first/last selectable option
|
||||
if (updatedByHeld) {
|
||||
bool noSelectableOption = true;
|
||||
if (kDown & KEY_DUP) {
|
||||
for (int i = currentMenu->menuIdx - 1; i >= 0; i--) {
|
||||
if (!currentMenu->settingsList->at(i)->IsHidden() &&
|
||||
!currentMenu->settingsList->at(i)->IsLocked()) {
|
||||
noSelectableOption = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (kDown & KEY_DDOWN) {
|
||||
for (size_t i = currentMenu->menuIdx + 1; i < currentMenu->settingsList->size(); i++) {
|
||||
if (!currentMenu->settingsList->at(i)->IsHidden() &&
|
||||
!currentMenu->settingsList->at(i)->IsLocked()) {
|
||||
noSelectableOption = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (noSelectableOption) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Loop through settings until an unlocked one is reached
|
||||
do {
|
||||
if ((kDown & KEY_DUP) != 0) {
|
||||
currentMenu->menuIdx--;
|
||||
}
|
||||
if ((kDown & KEY_DDOWN) != 0) {
|
||||
currentMenu->menuIdx++;
|
||||
}
|
||||
|
||||
// Bounds checking
|
||||
if (currentMenu->menuIdx == currentMenu->settingsList->size()) {
|
||||
currentMenu->menuIdx = 0;
|
||||
} else if (currentMenu->menuIdx == 0xFFFF) {
|
||||
currentMenu->menuIdx = static_cast<uint16_t>(currentMenu->settingsList->size() - 1);
|
||||
}
|
||||
|
||||
currentSetting = currentMenu->settingsList->at(currentMenu->menuIdx);
|
||||
} while (currentSetting->IsLocked() || currentSetting->IsHidden());
|
||||
}
|
||||
// All other menus except reset-to-defaults confirmation
|
||||
else if (currentMenu->mode != RESET_TO_DEFAULTS) {
|
||||
// Cancel if holding and reached first/last menu
|
||||
if (updatedByHeld) {
|
||||
if ((kDown & KEY_DUP && currentMenu->menuIdx == 0) ||
|
||||
(kDown & KEY_DDOWN && currentMenu->menuIdx == currentMenu->itemsList->size() - 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (kDown & KEY_DUP) {
|
||||
currentMenu->menuIdx--;
|
||||
}
|
||||
if (kDown & KEY_DDOWN) {
|
||||
currentMenu->menuIdx++;
|
||||
}
|
||||
|
||||
// Bounds checking
|
||||
uint16_t max = -1;
|
||||
if (currentMenu->mode == LOAD_PRESET || currentMenu->mode == DELETE_PRESET) { // Number of presets if applicable
|
||||
max = presetEntries.size();
|
||||
} else if (currentMenu->mode == GENERATE_MODE) { // Generate menu: 2 options
|
||||
max = 2;
|
||||
} else if (currentMenu->itemsList != nullptr) {
|
||||
max = currentMenu->itemsList->size(); // Default max: Number of items in menu
|
||||
}
|
||||
if (currentMenu->menuIdx == max) {
|
||||
currentMenu->menuIdx = 0;
|
||||
} else if (currentMenu->menuIdx == 0xFFFF) {
|
||||
currentMenu->menuIdx = max - 1;
|
||||
}
|
||||
|
||||
// Scroll Check
|
||||
if (currentMenu->menuIdx > currentMenu->settingBound + (MAX_SUBMENUS_ON_SCREEN - 1)) {
|
||||
currentMenu->settingBound = currentMenu->menuIdx - (MAX_SUBMENUS_ON_SCREEN - 1);
|
||||
} else if (currentMenu->menuIdx < currentMenu->settingBound) {
|
||||
currentMenu->settingBound = currentMenu->menuIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuUpdate(uint32_t kDown, bool updatedByHeld) {
|
||||
// Check for menu change
|
||||
// If user pressed A on a non-option, non-action menu, they're navigating to a new menu
|
||||
if (kDown & KEY_A && currentMenu->mode != OPTION_SUB_MENU && currentMenu->type != MenuType::Action) {
|
||||
if (currentMenu->itemsList->size() > currentMenu->menuIdx) {
|
||||
Menu* newMenu;
|
||||
newMenu = currentMenu->itemsList->at(currentMenu->menuIdx);
|
||||
menuList.push_back(newMenu);
|
||||
currentMenu = menuList.back();
|
||||
ModeChangeInit();
|
||||
kDown = 0;
|
||||
}
|
||||
// If they pressed B on any menu other than main, go backwards to the previous menu
|
||||
} else if (kDown & KEY_B && currentMenu->mode != MAIN_MENU) {
|
||||
// Want to reset generate menu when leaving
|
||||
if (currentMenu->mode == POST_GENERATE) {
|
||||
currentMenu->mode = GENERATE_MODE;
|
||||
}
|
||||
PrintTopScreen();
|
||||
menuList.pop_back();
|
||||
currentMenu = menuList.back();
|
||||
ModeChangeInit();
|
||||
kDown = 0;
|
||||
}
|
||||
|
||||
if (currentMenu->mode != GENERATE_MODE) {
|
||||
|
||||
// New Random Seed
|
||||
if (kDown & KEY_Y) {
|
||||
pastSeedLength = Settings::seed.length();
|
||||
Settings::seed = std::to_string(rand());
|
||||
seedChanged = true;
|
||||
}
|
||||
|
||||
// Input Custom Seed
|
||||
if (kDown & KEY_X) {
|
||||
pastSeedLength = Settings::seed.length();
|
||||
Settings::seed = GetInput("Enter Seed");
|
||||
seedChanged = true;
|
||||
}
|
||||
|
||||
// Reprint seed if it changed
|
||||
if (seedChanged) {
|
||||
std::string spaces = "";
|
||||
spaces.append(pastSeedLength, ' ');
|
||||
printf("\x1b[11;21H%s", spaces.c_str());
|
||||
printf("\x1b[11;21H%s", Settings::seed.c_str());
|
||||
seedChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Print current menu (if applicable)
|
||||
MoveCursor(kDown, updatedByHeld); // Move cursor, if applicable
|
||||
if (currentMenu->mode == MAIN_MENU) {
|
||||
PrintMainMenu();
|
||||
ClearDescription();
|
||||
} else if (currentMenu->mode == OPTION_SUB_MENU) {
|
||||
UpdateOptionSubMenu(kDown);
|
||||
PrintOptionSubMenu();
|
||||
} else if (currentMenu->mode == LOAD_PRESET) {
|
||||
UpdatePresetsMenu(kDown);
|
||||
PrintPresetsMenu();
|
||||
} else if (currentMenu->mode == DELETE_PRESET) {
|
||||
UpdatePresetsMenu(kDown);
|
||||
PrintPresetsMenu();
|
||||
} else if (currentMenu->mode == RESET_TO_DEFAULTS) {
|
||||
UpdateResetToDefaultsMenu(kDown);
|
||||
PrintResetToDefaultsMenu();
|
||||
} else if (currentMenu->mode == GENERATE_MODE) {
|
||||
UpdateGenerateMenu(kDown);
|
||||
if (currentMenu->mode != POST_GENERATE) {
|
||||
PrintGenerateMenu();
|
||||
}
|
||||
} else if (currentMenu->mode == SUB_MENU) {
|
||||
PrintSubMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ModeChangeInit() {
|
||||
if (currentMenu->mode == OPTION_SUB_MENU) {
|
||||
// loop through until we reach an unlocked setting
|
||||
while (currentMenu->settingsList->at(currentMenu->menuIdx)->IsLocked() ||
|
||||
currentMenu->settingsList->at(currentMenu->menuIdx)->IsHidden()) {
|
||||
currentMenu->menuIdx++;
|
||||
}
|
||||
currentSetting = currentMenu->settingsList->at(currentMenu->menuIdx);
|
||||
|
||||
} else if (currentMenu->mode == SAVE_PRESET) {
|
||||
ClearDescription();
|
||||
if (SaveSpecifiedPreset(GetInput("Preset Name").substr(0, 19), OptionCategory::Setting)) {
|
||||
printf("\x1b[24;5HPreset Saved!");
|
||||
printf("\x1b[26;5HPress B to return to the preset menu.");
|
||||
} else {
|
||||
printf("\x1b[24;5HFailed to save preset.");
|
||||
printf("\x1b[26;5HPress B to return to the preset menu.");
|
||||
}
|
||||
|
||||
} else if (currentMenu->mode == LOAD_PRESET || currentMenu->mode == DELETE_PRESET) {
|
||||
presetEntries = GetSettingsPresets();
|
||||
|
||||
} else if (currentMenu->mode == GENERATE_MODE) {
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateCustomCosmeticColors(uint32_t kDown) {
|
||||
if (kDown & KEY_A) {
|
||||
if (currentSetting->GetSelectedOptionText().compare(0, 8, Cosmetics::CUSTOM_COLOR_PREFIX) == 0) {
|
||||
std::string newColor = GetInput("Enter a 6 digit hex color").substr(0, 6);
|
||||
if (Cosmetics::ValidHexString(newColor)) {
|
||||
currentSetting->SetSelectedOptionText(Cosmetics::CustomColorOptionText(newColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOptionSubMenu(uint32_t kDown) {
|
||||
if ((kDown & KEY_DRIGHT) != 0) {
|
||||
currentSetting->NextOptionIndex();
|
||||
}
|
||||
if ((kDown & KEY_DLEFT) != 0) {
|
||||
currentSetting->PrevOptionIndex();
|
||||
}
|
||||
|
||||
// Bounds checking
|
||||
currentSetting->SanitizeSelectedOptionIndex();
|
||||
|
||||
currentSetting->SetVariable();
|
||||
Settings::ForceChange(kDown, currentSetting);
|
||||
UpdateCustomCosmeticColors(kDown);
|
||||
}
|
||||
|
||||
void UpdatePresetsMenu(uint32_t kDown) {
|
||||
// clear any potential message
|
||||
ClearDescription();
|
||||
if (kDown & KEY_A && currentMenu->mode == LOAD_PRESET && !presetEntries.empty()) {
|
||||
if (LoadPreset(presetEntries[currentMenu->menuIdx], OptionCategory::Setting)) {
|
||||
Settings::ResolveExcludedLocationConflicts();
|
||||
for (Menu* menu : Settings::GetAllOptionMenus()) {
|
||||
menu->ResetMenuIndex();
|
||||
}
|
||||
printf("\x1b[24;5HPreset Loaded!");
|
||||
} else {
|
||||
printf("\x1b[24;5HFailed to load preset.");
|
||||
}
|
||||
} else if (kDown & KEY_A && currentMenu->mode == DELETE_PRESET && !presetEntries.empty()) {
|
||||
if (DeletePreset(presetEntries[currentMenu->menuIdx], OptionCategory::Setting)) {
|
||||
presetEntries.erase(presetEntries.begin() + currentMenu->menuIdx);
|
||||
if (currentMenu->menuIdx == presetEntries.size()) { // Catch when last preset is deleted
|
||||
currentMenu->menuIdx--;
|
||||
}
|
||||
printf("\x1b[24;5HPreset Deleted.");
|
||||
} else {
|
||||
printf("\x1b[24;5HFailed to delete preset.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateResetToDefaultsMenu(uint32_t kDown) {
|
||||
// clear any potential message
|
||||
ClearDescription();
|
||||
if (kDown & KEY_A) {
|
||||
Settings::SetDefaultSettings();
|
||||
printf("\x1b[24;5HSettings have been reset to defaults.");
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateGenerateMenu(uint32_t kDown) {
|
||||
if ((kDown & KEY_A) != 0) {
|
||||
Settings::PlayOption = currentMenu->menuIdx;
|
||||
// GenerateRandomizer();
|
||||
// This is just a dummy mode to stop the prompt from appearing again
|
||||
currentMenu->mode = POST_GENERATE;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintMainMenu() {
|
||||
printf("\x1b[0;%dHMain Settings", 1 + (BOTTOM_WIDTH - 13) / 2);
|
||||
|
||||
for (uint8_t i = 0; i < MAX_SUBMENUS_ON_SCREEN; i++) {
|
||||
if (i >= Settings::mainMenu.size())
|
||||
break;
|
||||
|
||||
Menu* menu = Settings::mainMenu[i];
|
||||
|
||||
uint8_t row = 3 + i;
|
||||
// make the current menu green
|
||||
if (currentMenu->menuIdx == i) {
|
||||
printf("\x1b[%d;%dH%s>", row, 2, GREEN);
|
||||
printf("\x1b[%d;%dH%s%s", row, 3, menu->name.c_str(), RESET);
|
||||
} else {
|
||||
printf("\x1b[%d;%dH%s", row, 3, menu->name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintOptionSubMenu() {
|
||||
// bounds checking incase settings go off screen
|
||||
// this is complicated to account for hidden settings and there's probably a better way to do it
|
||||
uint16_t hiddenSettings = 0;
|
||||
uint16_t visibleSettings = 0;
|
||||
for (uint16_t i = currentMenu->settingBound; visibleSettings < MAX_SUBMENU_SETTINGS_ON_SCREEN; i++) {
|
||||
if (i >= currentMenu->settingsList->size()) {
|
||||
break;
|
||||
}
|
||||
if (currentMenu->settingsList->at(i)->IsHidden()) {
|
||||
hiddenSettings++;
|
||||
} else {
|
||||
visibleSettings++;
|
||||
}
|
||||
}
|
||||
bool isLastVisibleSetting = true;
|
||||
for (size_t i = currentMenu->menuIdx + 1; i < currentMenu->settingsList->size(); i++) {
|
||||
if (!currentMenu->settingsList->at(i)->IsHidden()) {
|
||||
isLastVisibleSetting = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (currentMenu->menuIdx >=
|
||||
currentMenu->settingBound - (isLastVisibleSetting ? 0 : 1) + MAX_SUBMENU_SETTINGS_ON_SCREEN + hiddenSettings) {
|
||||
currentMenu->settingBound = currentMenu->menuIdx;
|
||||
uint8_t offset = 0;
|
||||
// skip over hidden settings
|
||||
while (offset < MAX_SUBMENU_SETTINGS_ON_SCREEN - (isLastVisibleSetting ? 1 : 2)) {
|
||||
currentMenu->settingBound--;
|
||||
if (currentMenu->settingBound == 0) {
|
||||
break;
|
||||
}
|
||||
offset += currentMenu->settingsList->at(currentMenu->settingBound)->IsHidden() ? 0 : 1;
|
||||
}
|
||||
} else if (currentMenu->menuIdx < currentMenu->settingBound + 1) {
|
||||
currentMenu->settingBound = std::max(currentMenu->menuIdx - 1, 0);
|
||||
}
|
||||
|
||||
// print menu name
|
||||
printf("\x1b[0;%dH%s", 1 + (BOTTOM_WIDTH - currentMenu->name.length()) / 2, currentMenu->name.c_str());
|
||||
|
||||
// keep count of hidden settings to not make blank spaces appear in the list
|
||||
hiddenSettings = 0;
|
||||
|
||||
for (uint8_t i = 0; i - hiddenSettings < MAX_SUBMENU_SETTINGS_ON_SCREEN; i++) {
|
||||
// break if there are no more settings to print
|
||||
if (i + currentMenu->settingBound >= currentMenu->settingsList->size())
|
||||
break;
|
||||
|
||||
Option* setting = currentMenu->settingsList->at(i + currentMenu->settingBound);
|
||||
|
||||
uint8_t row = 3 + ((i - hiddenSettings) * 2);
|
||||
// make the current setting green
|
||||
if (currentMenu->menuIdx == i + currentMenu->settingBound) {
|
||||
printf("\x1b[%d;%dH%s>", row, 1, GREEN);
|
||||
printf("\x1b[%d;%dH%s:", row, 2, setting->GetName().data());
|
||||
printf("\x1b[%d;%dH%s%s", row, 26, setting->GetSelectedOptionText().data(), RESET);
|
||||
// dim to make a locked setting grey
|
||||
} else if (setting->IsLocked()) {
|
||||
printf("\x1b[%d;%dH%s%s:", row, 2, DIM, setting->GetName().data());
|
||||
printf("\x1b[%d;%dH%s%s", row, 26, setting->GetSelectedOptionText().data(), RESET);
|
||||
// don't display hidden settings
|
||||
} else if (setting->IsHidden()) {
|
||||
hiddenSettings++;
|
||||
continue;
|
||||
} else {
|
||||
printf("\x1b[%d;%dH%s:", row, 2, setting->GetName().data());
|
||||
printf("\x1b[%d;%dH%s", row, 26, setting->GetSelectedOptionText().data());
|
||||
}
|
||||
}
|
||||
|
||||
PrintOptionDescription();
|
||||
}
|
||||
|
||||
void PrintSubMenu() {
|
||||
printf("\x1b[0;%dH%s", 1 + (BOTTOM_WIDTH - currentMenu->name.length()) / 2, currentMenu->name.c_str());
|
||||
|
||||
for (uint8_t i = 0; i < MAX_SUBMENUS_ON_SCREEN; i++) {
|
||||
if (i >= currentMenu->itemsList->size())
|
||||
break;
|
||||
|
||||
uint8_t row = 3 + i;
|
||||
// make the current menu green
|
||||
if (currentMenu->menuIdx == currentMenu->settingBound + i) {
|
||||
printf("\x1b[%d;%dH%s>", row, 2, GREEN);
|
||||
printf("\x1b[%d;%dH%s%s", row, 3, currentMenu->itemsList->at(currentMenu->settingBound + i)->name.c_str(),
|
||||
RESET);
|
||||
} else {
|
||||
printf("\x1b[%d;%dH%s", row, 3, currentMenu->itemsList->at(currentMenu->settingBound + i)->name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintPresetsMenu() {
|
||||
if (presetEntries.empty()) {
|
||||
printf("\x1b[10;4HNo Presets Detected!");
|
||||
printf("\x1b[12;4HPress B to return to the preset menu.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMenu->mode == LOAD_PRESET) {
|
||||
printf("\x1b[0;%dHSelect a Preset to Load", 1 + (BOTTOM_WIDTH - 23) / 2);
|
||||
} else if (currentMenu->mode == DELETE_PRESET) {
|
||||
printf("\x1b[0;%dHSelect a Preset to Delete", 1 + (BOTTOM_WIDTH - 25) / 2);
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < MAX_SUBMENU_SETTINGS_ON_SCREEN; i++) {
|
||||
if (i >= presetEntries.size())
|
||||
break;
|
||||
|
||||
std::string preset = presetEntries[i];
|
||||
|
||||
uint8_t row = 3 + (i * 2);
|
||||
// make the current preset green
|
||||
if (currentMenu->menuIdx == i) {
|
||||
printf("\x1b[%d;%dH%s>", row, 14, GREEN);
|
||||
printf("\x1b[%d;%dH%s%s", row, 15, preset.c_str(), RESET);
|
||||
} else {
|
||||
printf("\x1b[%d;%dH%s", row, 15, preset.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintResetToDefaultsMenu() {
|
||||
printf("\x1b[10;4HPress A to reset to default settings.");
|
||||
printf("\x1b[12;4HPress B to return to the preset menu.");
|
||||
}
|
||||
|
||||
void PrintGenerateMenu() {
|
||||
printf("\x1b[3;%dHHow will you play?", 1+(BOTTOM_WIDTH-18)/2);
|
||||
std::vector<std::string> playOptions = {"3ds Console", "Citra Emulator"};
|
||||
|
||||
for (uint8_t i = 0; i < playOptions.size(); i++) {
|
||||
|
||||
std::string option = playOptions[i];
|
||||
uint8_t row = 6 + (i * 2);
|
||||
//make the current selection green
|
||||
if (currentMenu->menuIdx == i) {
|
||||
printf("\x1b[%d;%dH%s>", row, 14, GREEN);
|
||||
printf("\x1b[%d;%dH%s%s", row, 15, option.c_str(), RESET);
|
||||
} else {
|
||||
printf("\x1b[%d;%dH%s", row, 15, option.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClearDescription() {
|
||||
//clear the previous description
|
||||
std::string spaces = "";
|
||||
spaces.append(9 * TOP_WIDTH, ' ');
|
||||
printf("\x1b[22;0H%s", spaces.c_str());
|
||||
}
|
||||
|
||||
void PrintOptionDescription() {
|
||||
ClearDescription();
|
||||
std::string_view description = currentSetting->GetSelectedOptionDescription();
|
||||
|
||||
printf("\x1b[22;0H%s", description.data());
|
||||
}
|
||||
|
||||
std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings) {
|
||||
// if a blank seed was entered, make a random one
|
||||
srand(time(NULL));
|
||||
Settings::seed = std::to_string(rand());
|
||||
|
||||
int ret = Playthrough::Playthrough_Init(std::hash<std::string>{}(Settings::seed), cvarSettings);
|
||||
if (ret < 0) {
|
||||
if (ret == -1) { // Failed to generate after 5 tries
|
||||
printf("\n\nFailed to generate after 5 tries.\nPress B to go back to the menu.\nA different seed might be "
|
||||
"successful.");
|
||||
SPDLOG_INFO("\nRANDOMIZATION FAILED COMPLETELY. PLZ FIX\n");
|
||||
return "";
|
||||
} else {
|
||||
printf("\n\nError %d with fill.\nPress Select to exit or B to go back to the menu.\n", ret);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Restore settings that were set to a specific value for vanilla logic
|
||||
if (Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
for (Option* setting : Settings::vanillaLogicDefaults) {
|
||||
setting->RestoreDelayedOption();
|
||||
}
|
||||
Settings::Keysanity.RestoreDelayedOption();
|
||||
}
|
||||
|
||||
return "./Randomizer/" + Settings::seed + ".json";
|
||||
}
|
||||
|
||||
std::string GetInput(const char* hintText) {
|
||||
return std::string();
|
||||
}
|
52
soh/soh/Enhancements/randomizer/3drando/menu.hpp
Normal file
52
soh/soh/Enhancements/randomizer/3drando/menu.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "randomizerTypes.h"
|
||||
|
||||
#define MAIN_MENU 0
|
||||
#define OPTION_SUB_MENU 1
|
||||
#define SUB_MENU 2
|
||||
#define GENERATE_MODE 3
|
||||
#define LOAD_PRESET 4
|
||||
#define SAVE_PRESET 5
|
||||
#define DELETE_PRESET 6
|
||||
#define POST_GENERATE 7
|
||||
#define RESET_TO_DEFAULTS 8
|
||||
|
||||
#define MAX_SUBMENUS_ON_SCREEN 27
|
||||
#define MAX_SUBMENU_SETTINGS_ON_SCREEN 13
|
||||
#define TOP_WIDTH 50
|
||||
#define BOTTOM_WIDTH 40
|
||||
#define SCREEN_HEIGHT 30
|
||||
|
||||
#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"
|
||||
|
||||
void ModeChangeInit();
|
||||
void UpdateOptionSubMenu(uint32_t kDown);
|
||||
void UpdatePresetsMenu(uint32_t kdown);
|
||||
void UpdateResetToDefaultsMenu(uint32_t kdown);
|
||||
void UpdateGenerateMenu(uint32_t kDown);
|
||||
void PrintMainMenu();
|
||||
void PrintOptionSubMenu();
|
||||
void PrintSubMenu();
|
||||
void PrintPresetsMenu();
|
||||
void PrintResetToDefaultsMenu();
|
||||
void PrintGenerateMenu();
|
||||
void ClearDescription();
|
||||
void PrintOptionDescription();
|
||||
std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings);
|
||||
std::string GetInput(const char* hintText);
|
||||
|
||||
extern void MenuInit();
|
||||
extern void MenuUpdate(uint32_t kDown, bool updatedByHeld);
|
128
soh/soh/Enhancements/randomizer/3drando/music.cpp
Normal file
128
soh/soh/Enhancements/randomizer/3drando/music.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#include "music.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace Music {
|
||||
const std::array<SeqType, SEQ_COUNT> seqTypesMusic = {
|
||||
/* NA_BGM_FIELD */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_DUNGEON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_KAKARIKO_ADULT */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_ENEMY */ SEQ_NOSHUFFLE, // Temporarily unshuffled: Override plays incorrect in some areas, like Lake Hylia, by continuously repeating the start
|
||||
/* NA_BGM_BOSS00 */ SEQ_BGM_BATTLE,
|
||||
/* NA_BGM_FAIRY_DUNGEON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_MARKET */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_TITLE */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_LINK_HOUSE */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_GAME_OVER */ SEQ_FANFARE,
|
||||
/* NA_BGM_BOSS_CLEAR */ SEQ_FANFARE,
|
||||
/* NA_BGM_ITEM_GET */ SEQ_FANFARE,
|
||||
/* NA_BGM_OPENING_GANON */ SEQ_FANFARE,
|
||||
/* NA_BGM_HEART_GET */ SEQ_FANFARE,
|
||||
/* NA_BGM_OCA_LIGHT */ SEQ_OCARINA,
|
||||
/* NA_BGM_BUYO_DUNGEON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_KAKARIKO_KID */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_GODESS */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_HIME */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_FIRE_DUNGEON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_OPEN_TRE_BOX */ SEQ_FANFARE,
|
||||
/* NA_BGM_FORST_DUNGEON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_HIRAL_GARDEN */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_GANON_TOWER */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_RONRON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_GORON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_SPIRIT_STONE */ SEQ_FANFARE,
|
||||
/* NA_BGM_OCA_FLAME */ SEQ_OCARINA,
|
||||
/* NA_BGM_OCA_WIND */ SEQ_OCARINA,
|
||||
/* NA_BGM_OCA_WATER */ SEQ_OCARINA,
|
||||
/* NA_BGM_OCA_SOUL */ SEQ_OCARINA,
|
||||
/* NA_BGM_OCA_DARKNESS */ SEQ_OCARINA,
|
||||
/* NA_BGM_MIDDLE_BOSS */ SEQ_BGM_ERROR,
|
||||
/* NA_BGM_S_ITEM_GET */ SEQ_FANFARE,
|
||||
/* NA_BGM_SHRINE_OF_TIME */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_EVENT_CLEAR */ SEQ_FANFARE,
|
||||
/* NA_BGM_KOKIRI */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_OCA_YOUSEI */ SEQ_FANFARE,
|
||||
/* NA_BGM_MAYOIMORI */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_SOUL_DUNGEON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_HORSE */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_HORSE_GOAL */ SEQ_FANFARE,
|
||||
/* NA_BGM_INGO */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_MEDAL_GET */ SEQ_FANFARE,
|
||||
/* NA_BGM_OCA_SARIA */ SEQ_OCARINA,
|
||||
/* NA_BGM_OCA_EPONA */ SEQ_OCARINA,
|
||||
/* NA_BGM_OCA_ZELDA */ SEQ_OCARINA,
|
||||
/* NA_BGM_OCA_SUNMOON */ SEQ_NOSHUFFLE, /* Remove Sun's Song from the Ocarina pool for now due to bugs */
|
||||
/* NA_BGM_OCA_TIME */ SEQ_OCARINA,
|
||||
/* NA_BGM_OCA_STORM */ SEQ_OCARINA,
|
||||
/* NA_BGM_NAVI */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_DEKUNOKI */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_FUSHA */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_HIRAL_DEMO */ SEQ_NOSHUFFLE,
|
||||
/* NA_BGM_MINI_GAME */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_SEAK */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_ZORA */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_APPEAR */ SEQ_FANFARE,
|
||||
/* NA_BGM_ADULT_LINK */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_MASTER_SWORD */ SEQ_FANFARE,
|
||||
/* NA_BGM_INTRO_GANON */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_SHOP */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_KENJA */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_FILE_SELECT */ SEQ_NOSHUFFLE,
|
||||
/* NA_BGM_ICE_DUNGEON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_GATE_OPEN */ SEQ_NOSHUFFLE,
|
||||
/* NA_BGM_OWL */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_DARKNESS_DUNGEON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_AQUA_DUNGEON */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_BRIDGE */ SEQ_NOSHUFFLE,
|
||||
/* NA_BGM_SARIA */ SEQ_NOSHUFFLE,
|
||||
/* NA_BGM_GERUDO */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_DRUGSTORE */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_KOTAKE_KOUME */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_ESCAPE */ SEQ_BGM_EVENT,
|
||||
/* NA_BGM_UNDERGROUND */ SEQ_BGM_WORLD,
|
||||
/* NA_BGM_GANON_BATTLE_1 */ SEQ_BGM_BATTLE,
|
||||
/* NA_BGM_GANON_BATTLE_2 */ SEQ_BGM_BATTLE,
|
||||
/* NA_BGM_END_DEMO */ SEQ_NOSHUFFLE,
|
||||
/* NA_BGM_STAFF_1 */ SEQ_NOSHUFFLE,
|
||||
/* NA_BGM_STAFF_2 */ SEQ_NOSHUFFLE,
|
||||
/* NA_BGM_STAFF_3 */ SEQ_NOSHUFFLE,
|
||||
/* NA_BGM_STAFF_4 */ SEQ_NOSHUFFLE,
|
||||
/* NA_BGM_BOSS01 */ SEQ_BGM_BATTLE,
|
||||
/* NA_BGM_MINI_GAME_2 */ SEQ_BGM_ERROR,
|
||||
};
|
||||
|
||||
std::array<uint32_t, SEQ_COUNT> seqOverridesMusic;
|
||||
|
||||
/* Initializes the list of music overrides to unshuffled */
|
||||
void InitMusicRandomizer() {
|
||||
for(int i = 0; i < SEQ_COUNT; i++)
|
||||
seqOverridesMusic[i] = BGM_BASE + i;
|
||||
}
|
||||
|
||||
/* Shuffles the sequences grouping them by type */
|
||||
/* type is a bitmask of SeqType */
|
||||
void ShuffleSequences(int type) {
|
||||
std::vector<uint32_t> seqs;
|
||||
|
||||
// Get all sequences of the desired type(s) into a vector
|
||||
for (int i = 0; i < SEQ_COUNT; i++) {
|
||||
if (seqTypesMusic[i] & type) {
|
||||
seqs.push_back(seqOverridesMusic[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Shuffle the vector...
|
||||
for (std::size_t i = 0; i < seqs.size(); i++)
|
||||
{
|
||||
std::swap(seqs[i], seqs[rand() % seqs.size()]);
|
||||
}
|
||||
|
||||
// ...and feed it back into the overrides array
|
||||
for (int i = 0; i < SEQ_COUNT; i++) {
|
||||
if (seqTypesMusic[i] & type)
|
||||
{
|
||||
seqOverridesMusic[i] = seqs.back();
|
||||
seqs.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Music
|
29
soh/soh/Enhancements/randomizer/3drando/music.hpp
Normal file
29
soh/soh/Enhancements/randomizer/3drando/music.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Music {
|
||||
const uint32_t BGM_BASE = 0x1000585;
|
||||
const int SEQ_COUNT = 85;
|
||||
|
||||
enum SeqType {
|
||||
SEQ_NOSHUFFLE = 0,
|
||||
SEQ_BGM_WORLD = 1 << 0,
|
||||
SEQ_BGM_EVENT = 1 << 1,
|
||||
SEQ_BGM_BATTLE = 1 << 2,
|
||||
SEQ_OCARINA = 1 << 3,
|
||||
SEQ_FANFARE = 1 << 4,
|
||||
// A soundtrack in this category has the issue where if another soundtrack that isn't
|
||||
// in this category overrides it, it will keep playing when it should be stopped.
|
||||
// For example when beating a mini-boss or finishing the zora diving game.
|
||||
SEQ_BGM_ERROR = 1 << 5,
|
||||
};
|
||||
|
||||
extern const std::array<SeqType, SEQ_COUNT> seqTypesMusic;
|
||||
extern std::array<uint32_t, SEQ_COUNT> seqOverridesMusic;
|
||||
|
||||
void InitMusicRandomizer();
|
||||
void ShuffleSequences(int type);
|
||||
} // namespace Music
|
25
soh/soh/Enhancements/randomizer/3drando/patch.cpp
Normal file
25
soh/soh/Enhancements/randomizer/3drando/patch.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "patch.hpp"
|
||||
|
||||
#include "cosmetics.hpp"
|
||||
#include "custom_messages.hpp"
|
||||
#include "music.hpp"
|
||||
#include "sound_effects.hpp"
|
||||
#include "shops.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "entrance.hpp"
|
||||
#include "hints.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// For specification on the IPS file format, visit: https://zerosoft.zophar.net/ips.php
|
||||
|
||||
using FILEPtr = std::unique_ptr<FILE, decltype(&std::fclose)>;
|
||||
|
||||
void WriteFloatToBuffer(std::vector<char>& buffer, float f, size_t offset) {
|
||||
memcpy(buffer.data() + offset, &f, sizeof(float));
|
||||
}
|
12
soh/soh/Enhancements/randomizer/3drando/patch.hpp
Normal file
12
soh/soh/Enhancements/randomizer/3drando/patch.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <set>
|
||||
#include "playthrough.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
#define V_TO_P(addr) (addr - 0x100000)
|
||||
#define P_TO_V(offset) (offset + 0x100000)
|
||||
#define PATCH_CONSOLE 0
|
||||
#define PATCH_CITRA 1
|
||||
#define PATCH_SIZE_MAX 65535
|
||||
|
||||
bool WriteAllPatches();
|
97
soh/soh/Enhancements/randomizer/3drando/playthrough.cpp
Normal file
97
soh/soh/Enhancements/randomizer/3drando/playthrough.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
#include "playthrough.hpp"
|
||||
|
||||
#include "custom_messages.hpp"
|
||||
#include "fill.hpp"
|
||||
#include "location_access.hpp"
|
||||
#include "logic.hpp"
|
||||
#include "random.hpp"
|
||||
#include "spoiler_log.hpp"
|
||||
#include "randomizerTypes.h"
|
||||
|
||||
namespace Playthrough {
|
||||
|
||||
int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings) {
|
||||
// initialize the RNG with just the seed incase any settings need to be
|
||||
// resolved to something random
|
||||
Random_Init(seed);
|
||||
|
||||
overrides.clear();
|
||||
CustomMessages::ClearMessages();
|
||||
ItemReset();
|
||||
HintReset();
|
||||
Areas::AccessReset();
|
||||
|
||||
Settings::UpdateSettings(cvarSettings);
|
||||
// once the settings have been finalized turn them into a string for hashing
|
||||
std::string settingsStr;
|
||||
for (Menu* menu : Settings::GetAllOptionMenus()) {
|
||||
// don't go through non-menus
|
||||
if (menu->mode != OPTION_SUB_MENU) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < menu->settingsList->size(); i++) {
|
||||
Option* setting = menu->settingsList->at(i);
|
||||
if (setting->IsCategory(OptionCategory::Setting)) {
|
||||
settingsStr += setting->GetSelectedOptionText();
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int finalHash = std::hash<std::string>{}(Settings::seed + settingsStr);
|
||||
Random_Init(finalHash);
|
||||
|
||||
Logic::UpdateHelpers();
|
||||
|
||||
if (Settings::Logic.Is(LOGIC_VANILLA)) {
|
||||
VanillaFill(); // Just place items in their vanilla locations
|
||||
} else { // Fill locations with logic
|
||||
int ret = Fill();
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
GenerateHash();
|
||||
WriteIngameSpoilerLog();
|
||||
|
||||
if (Settings::GenerateSpoilerLog) {
|
||||
// write logs
|
||||
printf("\x1b[11;10HWriting Spoiler Log...");
|
||||
if (SpoilerLog_Write(cvarSettings[RSK_LANGUAGE])) {
|
||||
printf("Done");
|
||||
} else {
|
||||
printf("Failed");
|
||||
}
|
||||
#ifdef ENABLE_DEBUG
|
||||
printf("\x1b[11;10HWriting Placement Log...");
|
||||
if (PlacementLog_Write()) {
|
||||
printf("Done\n");
|
||||
} else {
|
||||
printf("Failed\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
playthroughLocations.clear();
|
||||
wothLocations.clear();
|
||||
playthroughBeatable = false;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// used for generating a lot of seeds at once
|
||||
int Playthrough_Repeat(int count /*= 1*/) {
|
||||
printf("\x1b[0;0HGENERATING %d SEEDS", count);
|
||||
uint32_t repeatedSeed = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
repeatedSeed = rand() % 0xFFFFFFFF;
|
||||
Settings::seed = std::to_string(repeatedSeed);
|
||||
CitraPrint("testing seed: " + Settings::seed);
|
||||
ClearProgress();
|
||||
// Playthrough_Init(std::hash<std::string>{}(Settings::seed));
|
||||
printf("\x1b[15;15HSeeds Generated: %d\n", i + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
} // namespace Playthrough
|
9
soh/soh/Enhancements/randomizer/3drando/playthrough.hpp
Normal file
9
soh/soh/Enhancements/randomizer/3drando/playthrough.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include "item_location.hpp"
|
||||
|
||||
namespace Playthrough {
|
||||
int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings);
|
||||
int Playthrough_Repeat(int count = 1);
|
||||
}
|
38
soh/soh/Enhancements/randomizer/3drando/pool_functions.hpp
Normal file
38
soh/soh/Enhancements/randomizer/3drando/pool_functions.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
||||
template <typename T, typename Predicate>
|
||||
static void erase_if(std::vector<T>& vector, Predicate pred) {
|
||||
vector.erase(std::remove_if(begin(vector), end(vector), pred), end(vector));
|
||||
}
|
||||
|
||||
template <typename T, typename Predicate>
|
||||
std::vector<T> FilterFromPool(std::vector<T>& vector, Predicate pred, bool eraseAfterFilter = false) {
|
||||
std::vector<T> filteredPool = {};
|
||||
std::copy_if(vector.begin(), vector.end(), std::back_inserter(filteredPool), pred);
|
||||
|
||||
if (eraseAfterFilter) {
|
||||
erase_if(vector, pred);
|
||||
}
|
||||
|
||||
return filteredPool;
|
||||
}
|
||||
|
||||
template <typename T, typename Predicate>
|
||||
std::vector<T> FilterAndEraseFromPool(std::vector<T>& vector, Predicate pred) {
|
||||
return FilterFromPool(vector, pred, true);
|
||||
}
|
||||
|
||||
template <typename T, typename FromPool>
|
||||
void AddElementsToPool(std::vector<T>& toPool, const FromPool& fromPool) {
|
||||
toPool.insert(toPool.end(), std::cbegin(fromPool), std::cend(fromPool));
|
||||
}
|
||||
|
||||
template <typename T, typename Container>
|
||||
bool ElementInContainer(T& element, const Container& container) {
|
||||
return std::find(container.begin(), container.end(), element) != container.end();
|
||||
}
|
202
soh/soh/Enhancements/randomizer/3drando/preset.cpp
Normal file
202
soh/soh/Enhancements/randomizer/3drando/preset.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
#include "preset.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include "category.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "tinyxml2.h"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static const std::string CACHED_SETTINGS_FILENAME = "CACHED_SETTINGS";
|
||||
static const std::string CACHED_COSMETICS_FILENAME = "CACHED_COSMETICS";
|
||||
|
||||
static std::string_view GetBasePath(OptionCategory category) {
|
||||
static constexpr std::array<std::string_view, 2> paths{
|
||||
"/3ds/presets/oot3dr/settings/",
|
||||
"/3ds/presets/oot3dr/cosmetics/",
|
||||
};
|
||||
|
||||
switch(category) {
|
||||
case OptionCategory::Setting :
|
||||
case OptionCategory::Cosmetic :
|
||||
return paths[static_cast<size_t>(category)];
|
||||
case OptionCategory::Toggle :
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//Creates preset directories if they don't exist
|
||||
bool CreatePresetDirectories() {
|
||||
//Create the 3ds directory if it doesn't exist
|
||||
std::filesystem::create_directory("./3ds");
|
||||
//Create the presets directory if it doesn't exist
|
||||
std::filesystem::create_directory("./3ds/presets");
|
||||
//Create the oot3d directory if it doesn't exist
|
||||
std::filesystem::create_directory("./3ds/presets/oot3dr");
|
||||
//Create the cosmetics directory if it doesn't exist
|
||||
std::filesystem::create_directory("./3ds/presets/oot3dr/cosmetics");
|
||||
//Create the settings directory if it doesn't exist
|
||||
std::filesystem::create_directory("./3ds/presets/oot3dr/settings");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Gets the preset filenames
|
||||
std::vector<std::string> GetSettingsPresets() {
|
||||
std::vector<std::string> presetEntries = {};
|
||||
for (const auto& entry : fs::directory_iterator(GetBasePath(OptionCategory::Setting))) {
|
||||
if(entry.path().stem().string() != CACHED_SETTINGS_FILENAME) {
|
||||
presetEntries.push_back(entry.path().stem().string());
|
||||
}
|
||||
}
|
||||
return presetEntries;
|
||||
}
|
||||
|
||||
static std::string PresetPath(std::string_view presetName, OptionCategory category) {
|
||||
return std::string(GetBasePath(category)).append(presetName).append(".xml");
|
||||
}
|
||||
|
||||
// Presets are now saved as XML files using the tinyxml2 library.
|
||||
// Documentation: https://leethomason.github.io/tinyxml2/index.html
|
||||
bool SavePreset(std::string_view presetName, OptionCategory category) {
|
||||
using namespace tinyxml2;
|
||||
|
||||
XMLDocument preset = XMLDocument(false);
|
||||
|
||||
// Create and insert the XML declaration
|
||||
preset.InsertEndChild(preset.NewDeclaration());
|
||||
|
||||
// Create the root node
|
||||
XMLElement* rootNode = preset.NewElement("settings");
|
||||
preset.InsertEndChild(rootNode);
|
||||
|
||||
for (Menu* menu : Settings::GetAllOptionMenus()) {
|
||||
if (menu->mode != OPTION_SUB_MENU) {
|
||||
continue;
|
||||
}
|
||||
for (const Option* setting : *menu->settingsList) {
|
||||
if (!setting->IsCategory(category)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
XMLElement* newSetting = rootNode->InsertNewChildElement("setting");
|
||||
newSetting->SetAttribute("name", RemoveLineBreaks(setting->GetName()).c_str());
|
||||
newSetting->SetText(setting->GetSelectedOptionText().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
XMLError e = preset.SaveFile(PresetPath(presetName, category).c_str());
|
||||
return e == XML_SUCCESS;
|
||||
}
|
||||
|
||||
//Read the preset XML file
|
||||
bool LoadPreset(std::string_view presetName, OptionCategory category) {
|
||||
using namespace tinyxml2;
|
||||
|
||||
XMLDocument preset;
|
||||
XMLError e = preset.LoadFile(PresetPath(presetName, category).c_str());
|
||||
if (e != XML_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
XMLElement* rootNode = preset.RootElement();
|
||||
if (strcmp(rootNode->Name(), "settings") != 0) {
|
||||
// We do not have our <settings> root node, so it may be the old structure. We don't support that one anymore.
|
||||
return false;
|
||||
}
|
||||
|
||||
XMLElement* curNode = rootNode->FirstChildElement();
|
||||
|
||||
for (Menu* menu : Settings::GetAllOptionMenus()) {
|
||||
if (menu->mode != OPTION_SUB_MENU) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Option* setting : *menu->settingsList) {
|
||||
if (!setting->IsCategory(category)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Since presets are saved linearly, we can simply loop through the nodes as
|
||||
// we loop through the settings to find most of the matching elements.
|
||||
const std::string& settingToFind = RemoveLineBreaks(setting->GetName());
|
||||
if (settingToFind == RemoveLineBreaks(curNode->Attribute("name"))) {
|
||||
setting->SetSelectedIndexByString(curNode->GetText());
|
||||
curNode = curNode->NextSiblingElement();
|
||||
} else {
|
||||
// If the current setting and element don't match, then search
|
||||
// linearly from the beginning. This will get us back on track if the
|
||||
// next setting and element line up with each other.
|
||||
curNode = rootNode->FirstChildElement();
|
||||
while (curNode != nullptr) {
|
||||
if (settingToFind == RemoveLineBreaks(curNode->Attribute("name"))) {
|
||||
setting->SetSelectedIndexByString(curNode->GetText());
|
||||
curNode = curNode->NextSiblingElement();
|
||||
break;
|
||||
}
|
||||
curNode = curNode->NextSiblingElement();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset to the beginning if we reached the end.
|
||||
if (curNode == nullptr) {
|
||||
curNode = rootNode->FirstChildElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//Delete the selected preset
|
||||
bool DeletePreset(std::string_view presetName, OptionCategory category) {
|
||||
const std::string filepath = PresetPath(presetName, category);
|
||||
|
||||
std::filesystem::remove(filepath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Saves the new preset to a file
|
||||
bool SaveSpecifiedPreset(std::string_view presetName, OptionCategory category) {
|
||||
//don't save if the user cancelled
|
||||
if (presetName.empty()) {
|
||||
return false;
|
||||
}
|
||||
return SavePreset(presetName, category);
|
||||
}
|
||||
|
||||
void SaveCachedSettings() {
|
||||
SavePreset(CACHED_SETTINGS_FILENAME, OptionCategory::Setting);
|
||||
}
|
||||
|
||||
void LoadCachedSettings() {
|
||||
//If cache file exists, load it
|
||||
for (const auto& entry : fs::directory_iterator(GetBasePath(OptionCategory::Setting))) {
|
||||
if(entry.path().stem().string() == CACHED_SETTINGS_FILENAME) {
|
||||
//File exists, open
|
||||
LoadPreset(CACHED_SETTINGS_FILENAME, OptionCategory::Setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SaveCachedCosmetics() {
|
||||
return SavePreset(CACHED_COSMETICS_FILENAME, OptionCategory::Cosmetic);
|
||||
}
|
||||
|
||||
void LoadCachedCosmetics() {
|
||||
//If cache file exists, load it
|
||||
for (const auto& entry : fs::directory_iterator(GetBasePath(OptionCategory::Cosmetic))) {
|
||||
if(entry.path().stem().string() == CACHED_COSMETICS_FILENAME) {
|
||||
//File exists, open
|
||||
LoadPreset(CACHED_COSMETICS_FILENAME, OptionCategory::Cosmetic);
|
||||
}
|
||||
}
|
||||
}
|
17
soh/soh/Enhancements/randomizer/3drando/preset.hpp
Normal file
17
soh/soh/Enhancements/randomizer/3drando/preset.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
enum class OptionCategory;
|
||||
|
||||
bool CreatePresetDirectories();
|
||||
std::vector<std::string> GetSettingsPresets();
|
||||
bool SavePreset(std::string_view presetName, OptionCategory category);
|
||||
bool LoadPreset(std::string_view presetName, OptionCategory category);
|
||||
bool DeletePreset(std::string_view presetName, OptionCategory category);
|
||||
bool SaveSpecifiedPreset(std::string_view presetName, OptionCategory category);
|
||||
void SaveCachedSettings();
|
||||
void LoadCachedSettings();
|
||||
bool SaveCachedCosmetics();
|
||||
void LoadCachedCosmetics();
|
27
soh/soh/Enhancements/randomizer/3drando/rando_main.cpp
Normal file
27
soh/soh/Enhancements/randomizer/3drando/rando_main.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "menu.hpp"
|
||||
#include "hint_list.hpp"
|
||||
#include "item_list.hpp"
|
||||
#include "item_location.hpp"
|
||||
#include "location_access.hpp"
|
||||
#include "rando_main.hpp"
|
||||
// #include <soh/Enhancements/randomizer.h>
|
||||
#include <Cvar.h>
|
||||
#include <GameSettings.h>
|
||||
|
||||
#define TICKS_PER_SEC 268123480.0
|
||||
|
||||
void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarSettings) {
|
||||
HintTable_Init();
|
||||
ItemTable_Init();
|
||||
LocationTable_Init();
|
||||
|
||||
// std::string settingsFileName = "./randomizer/latest_settings.json";
|
||||
// CVar_SetString("gLoadedPreset", settingsFileName.c_str());
|
||||
|
||||
std::string fileName = GenerateRandomizer(cvarSettings);
|
||||
CVar_SetString("gSpoilerLog", fileName.c_str());
|
||||
|
||||
Game::SaveSettings();
|
||||
Game::LoadSettings();
|
||||
CVar_SetS32("gNewSeedGenerated", 1);
|
||||
}
|
5
soh/soh/Enhancements/randomizer/3drando/rando_main.hpp
Normal file
5
soh/soh/Enhancements/randomizer/3drando/rando_main.hpp
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
namespace RandoMain {
|
||||
void GenerateRando(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings);
|
||||
}
|
29
soh/soh/Enhancements/randomizer/3drando/random.cpp
Normal file
29
soh/soh/Enhancements/randomizer/3drando/random.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "random.hpp"
|
||||
|
||||
#include <random>
|
||||
|
||||
static bool init = false;
|
||||
static std::mt19937_64 generator;
|
||||
|
||||
//Initialize with seed specified
|
||||
void Random_Init(uint32_t seed) {
|
||||
init = true;
|
||||
generator = std::mt19937_64{seed};
|
||||
}
|
||||
|
||||
//Returns a random integer in range [min, max-1]
|
||||
uint32_t Random(int min, int max) {
|
||||
if (!init) {
|
||||
//No seed given, get a random number from device to seed
|
||||
const auto seed = static_cast<uint32_t>(std::random_device{}());
|
||||
Random_Init(seed);
|
||||
}
|
||||
std::uniform_int_distribution<uint32_t> distribution(min, max-1);
|
||||
return distribution(generator);
|
||||
}
|
||||
|
||||
//Returns a random floating point number in [0.0, 1.0]
|
||||
double RandomDouble() {
|
||||
std::uniform_real_distribution<double> distribution(0.0, 1.0);
|
||||
return distribution(generator);
|
||||
}
|
46
soh/soh/Enhancements/randomizer/3drando/random.hpp
Normal file
46
soh/soh/Enhancements/randomizer/3drando/random.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
void Random_Init(uint32_t seed);
|
||||
uint32_t Random(int min, int max);
|
||||
double RandomDouble();
|
||||
|
||||
//Get a random element from a vector or array
|
||||
template <typename T>
|
||||
T RandomElement(std::vector<T>& vector, bool erase) {
|
||||
const auto idx = Random(0, vector.size());
|
||||
const T selected = vector[idx];
|
||||
if (erase) {
|
||||
vector.erase(vector.begin() + idx);
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
template <typename Container>
|
||||
auto& RandomElement(Container& container) {
|
||||
return container[Random(0, std::size(container))];
|
||||
}
|
||||
template <typename Container>
|
||||
const auto& RandomElement(const Container& container) {
|
||||
return container[Random(0, std::size(container))];
|
||||
}
|
||||
|
||||
//Shuffle items within a vector or array
|
||||
template <typename T>
|
||||
void Shuffle(std::vector<T>& vector) {
|
||||
for (std::size_t i = 0; i + 1 < vector.size(); i++)
|
||||
{
|
||||
std::swap(vector[i], vector[Random(i, vector.size())]);
|
||||
}
|
||||
}
|
||||
template <typename T, std::size_t size>
|
||||
void Shuffle(std::array<T, size>& arr) {
|
||||
for (std::size_t i = 0; i + 1 < arr.size(); i++)
|
||||
{
|
||||
std::swap(arr[i], arr[Random(i, arr.size())]);
|
||||
}
|
||||
}
|
4
soh/soh/Enhancements/randomizer/3drando/randomizer.hpp
Normal file
4
soh/soh/Enhancements/randomizer/3drando/randomizer.hpp
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#define RANDOMIZER_VERSION "v3.1"
|
||||
#define COMMIT_NUMBER "develop"
|
1696
soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp
Normal file
1696
soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp
Normal file
File diff suppressed because it is too large
Load Diff
541
soh/soh/Enhancements/randomizer/3drando/setting_descriptions.hpp
Normal file
541
soh/soh/Enhancements/randomizer/3drando/setting_descriptions.hpp
Normal file
@ -0,0 +1,541 @@
|
||||
#pragma once
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
using string_view = std::string_view;
|
||||
|
||||
extern string_view openRandomize;
|
||||
extern string_view worldRandomize;
|
||||
extern string_view shuffleRandomize;
|
||||
extern string_view dungeonRandomize;
|
||||
|
||||
extern string_view logicGlitchless;
|
||||
extern string_view logicGlitched;
|
||||
extern string_view logicNoLogic;
|
||||
extern string_view logicVanilla;
|
||||
|
||||
extern string_view forestOpen;
|
||||
extern string_view forestClosed;
|
||||
extern string_view forestClosedDeku;
|
||||
|
||||
extern string_view kakGateOpen;
|
||||
extern string_view kakGateClosed;
|
||||
|
||||
extern string_view doorOfTimeOpen;
|
||||
extern string_view doorOfTimeClosed;
|
||||
extern string_view doorOfTimeIntended;
|
||||
|
||||
extern string_view fountainNormal;
|
||||
extern string_view fountainAdult;
|
||||
extern string_view fountainOpen;
|
||||
|
||||
extern string_view gerudoNormal;
|
||||
extern string_view gerudoFast;
|
||||
extern string_view gerudoOpen;
|
||||
|
||||
extern string_view bridgeOpen;
|
||||
extern string_view bridgeVanilla;
|
||||
extern string_view bridgeStones;
|
||||
extern string_view bridgeMedallions;
|
||||
extern string_view bridgeRewards;
|
||||
extern string_view bridgeDungeons;
|
||||
extern string_view bridgeTokens;
|
||||
|
||||
extern string_view bridgeStoneCountDesc;
|
||||
extern string_view bridgeMedallionCountDesc;
|
||||
extern string_view bridgeRewardCountDesc;
|
||||
extern string_view bridgeDungeonCountDesc;
|
||||
extern string_view bridgeTokenCountDesc;
|
||||
|
||||
extern string_view randomGanonsTrialsDesc;
|
||||
|
||||
extern string_view ganonsTrialCountDesc;
|
||||
|
||||
extern string_view ageDesc;
|
||||
|
||||
extern string_view shuffleEntrancesDesc;
|
||||
|
||||
extern string_view dungeonEntrancesDesc;
|
||||
|
||||
extern string_view overworldEntrancesDesc;
|
||||
|
||||
extern string_view grottoEntrancesDesc;
|
||||
|
||||
extern string_view interiorEntrancesOff;
|
||||
extern string_view interiorEntrancesSimple;
|
||||
extern string_view interiorEntrancesAll;
|
||||
|
||||
extern string_view bombchuLogicDesc;
|
||||
|
||||
extern string_view defaultAmmoDropsDesc;
|
||||
extern string_view bombchuDropsDesc;
|
||||
extern string_view noAmmoDropsDesc;
|
||||
|
||||
extern string_view defaultHeartDropsDesc;
|
||||
extern string_view noHeartDropsDesc;
|
||||
extern string_view noHeartRefillDesc;
|
||||
extern string_view scarceHeartsDesc;
|
||||
|
||||
extern string_view mqDungeonCountDesc;
|
||||
extern string_view setDungeonTypesDesc;
|
||||
|
||||
extern string_view shuffleRewardsEndOfDungeon;
|
||||
extern string_view shuffleRewardsAnyDungeon;
|
||||
extern string_view shuffleRewardsOverworld;
|
||||
extern string_view shuffleRewardsAnywhere;
|
||||
|
||||
extern string_view linksPocketDungeonReward;
|
||||
extern string_view linksPocketAdvancement;
|
||||
extern string_view linksPocketAnything;
|
||||
extern string_view linksPocketNothing;
|
||||
|
||||
extern string_view songsSongLocations;
|
||||
extern string_view songsDungeonRewards;
|
||||
extern string_view songsAllLocations;
|
||||
|
||||
extern string_view shopsOff;
|
||||
extern string_view shopsZero;
|
||||
extern string_view shopsOne;
|
||||
extern string_view shopsTwo;
|
||||
extern string_view shopsThree;
|
||||
extern string_view shopsFour;
|
||||
extern string_view shopsRandom;
|
||||
|
||||
extern string_view tokensOff;
|
||||
extern string_view tokensDungeon;
|
||||
extern string_view tokensOverworld;
|
||||
extern string_view tokensAllTokens;
|
||||
|
||||
extern string_view scrubsOff;
|
||||
extern string_view scrubsAffordable;
|
||||
extern string_view scrubsExpensive;
|
||||
extern string_view scrubsRandomPrices;
|
||||
|
||||
extern string_view shuffleCowsDesc;
|
||||
|
||||
extern string_view kokiriSwordDesc;
|
||||
|
||||
extern string_view ocarinasDesc;
|
||||
|
||||
extern string_view weirdEggDesc;
|
||||
|
||||
extern string_view gerudoTokenDesc;
|
||||
|
||||
extern string_view magicBeansDesc;
|
||||
|
||||
extern string_view merchantsDesc;
|
||||
extern string_view merchantsHintsDesc;
|
||||
|
||||
extern string_view adultTradeDesc;
|
||||
|
||||
extern string_view chestMinigameDesc;
|
||||
|
||||
extern string_view mapCompassStartWith;
|
||||
extern string_view mapCompassVanilla;
|
||||
extern string_view mapCompassOwnDungeon;
|
||||
extern string_view mapCompassAnyDungeon;
|
||||
extern string_view mapCompassOverworld;
|
||||
extern string_view mapCompassAnywhere;
|
||||
|
||||
extern string_view smallKeyStartWith;
|
||||
extern string_view smallKeyVanilla;
|
||||
extern string_view smallKeyOwnDungeon;
|
||||
extern string_view smallKeyAnyDungeon;
|
||||
extern string_view smallKeyOverworld;
|
||||
extern string_view smallKeyAnywhere;
|
||||
|
||||
extern string_view gerudoKeysVanilla;
|
||||
extern string_view gerudoKeysAnyDungeon;
|
||||
extern string_view gerudoKeysOverworld;
|
||||
extern string_view gerudoKeysAnywhere;
|
||||
|
||||
extern string_view keyRingDesc;
|
||||
|
||||
extern string_view bossKeyStartWith;
|
||||
extern string_view bossKeyVanilla;
|
||||
extern string_view bossKeyOwnDungeon;
|
||||
extern string_view bossKeyAnyDungeon;
|
||||
extern string_view bossKeyOverworld;
|
||||
extern string_view bossKeyAnywhere;
|
||||
|
||||
extern string_view ganonKeyStartWith;
|
||||
extern string_view ganonKeyVanilla;
|
||||
extern string_view ganonKeyOwnDungeon;
|
||||
extern string_view ganonKeyAnyDungeon;
|
||||
extern string_view ganonKeyOverworld;
|
||||
extern string_view ganonKeyAnywhere;
|
||||
extern string_view ganonKeyLACS;
|
||||
|
||||
extern string_view lacsMedallionCountDesc;
|
||||
extern string_view lacsStoneCountDesc;
|
||||
extern string_view lacsRewardCountDesc;
|
||||
extern string_view lacsDungeonCountDesc;
|
||||
extern string_view lacsTokenCountDesc;
|
||||
|
||||
extern string_view childStealthDesc;
|
||||
|
||||
extern string_view skipTowerEscapeDesc;
|
||||
|
||||
extern string_view skipEponaRaceDesc;
|
||||
|
||||
extern string_view skipMinigamePhasesDesc;
|
||||
|
||||
extern string_view freeScarecrowDesc;
|
||||
|
||||
extern string_view fourPoesDesc;
|
||||
|
||||
extern string_view lakeHyliaOwlDesc;
|
||||
|
||||
extern string_view bigPoeTargetCountDesc;
|
||||
|
||||
extern string_view numRequiredCuccosDesc;
|
||||
|
||||
extern string_view kingZoraSpeedFast;
|
||||
extern string_view kingZoraSpeedVanilla;
|
||||
extern string_view kingZoraSpeedRandom;
|
||||
|
||||
extern string_view completeMaskDesc;
|
||||
|
||||
extern string_view quickTextDesc0;
|
||||
extern string_view quickTextDesc1;
|
||||
extern string_view quickTextDesc2;
|
||||
extern string_view quickTextDesc3;
|
||||
extern string_view skipSongReplaysDesc;
|
||||
|
||||
extern string_view keepFWWarpPointDesc;
|
||||
|
||||
extern string_view fastBunnyHoodDesc;
|
||||
|
||||
extern string_view gossipStonesHintsDesc;
|
||||
|
||||
extern string_view obscureHintsDesc;
|
||||
extern string_view ambiguousHintsDesc;
|
||||
extern string_view clearHintsDesc;
|
||||
|
||||
extern string_view uselessHintsDesc;
|
||||
extern string_view balancedHintsDesc;
|
||||
extern string_view strongHintsDesc;
|
||||
extern string_view veryStrongHintsDesc;
|
||||
|
||||
extern string_view compassesShowRewardsDesc;
|
||||
extern string_view compassesShowWotHDesc;
|
||||
extern string_view mapsShowDungeonModesDesc;
|
||||
|
||||
extern string_view damageMultiDesc;
|
||||
|
||||
extern string_view startingTimeDesc;
|
||||
|
||||
extern string_view locationsReachableDesc;
|
||||
extern string_view nightGSDesc;
|
||||
|
||||
extern string_view chestAnimDesc;
|
||||
|
||||
extern string_view chestSizeDesc;
|
||||
|
||||
extern string_view ingameSpoilersShowDesc;
|
||||
extern string_view ingameSpoilersHideDesc;
|
||||
|
||||
extern string_view menuButtonDesc;
|
||||
|
||||
extern string_view startWithConsumablesDesc;
|
||||
|
||||
extern string_view startWithMaxRupeesDesc;
|
||||
|
||||
extern string_view itemPoolPlentiful;
|
||||
extern string_view itemPoolBalanced;
|
||||
extern string_view itemPoolScarce;
|
||||
extern string_view itemPoolMinimal;
|
||||
|
||||
extern string_view iceTrapsOff;
|
||||
extern string_view iceTrapsNormal;
|
||||
extern string_view iceTrapsExtra;
|
||||
extern string_view iceTrapsMayhem;
|
||||
extern string_view iceTrapsOnslaught;
|
||||
|
||||
extern string_view removeDDDesc;
|
||||
|
||||
extern string_view progGoronSword;
|
||||
|
||||
extern string_view faroresWindAnywhereDesc;
|
||||
|
||||
extern string_view ageRestrictionsDesc;
|
||||
extern string_view adultStickDesc;
|
||||
extern string_view adultBoomerangDesc;
|
||||
extern string_view childHammerDesc;
|
||||
extern string_view adultSlingshotDesc;
|
||||
extern string_view childBowDesc;
|
||||
extern string_view childHookshotDesc;
|
||||
extern string_view childIronBootsDesc;
|
||||
extern string_view childHoverBootsDesc;
|
||||
extern string_view adultMasksDesc;
|
||||
extern string_view adultKokiriSwordDesc;
|
||||
extern string_view childMasterSwordDesc;
|
||||
extern string_view childBiggoronSwordDesc;
|
||||
extern string_view adultDekuShieldDesc;
|
||||
extern string_view childMirrorShieldDesc;
|
||||
extern string_view childGoronTunicDesc;
|
||||
extern string_view childZoraTunicDesc;
|
||||
|
||||
extern string_view gkDurabilityVanilla;
|
||||
extern string_view gkDurabilityRandomRisk;
|
||||
extern string_view gkDurabilityRandomSafe;
|
||||
|
||||
extern string_view mp_EnabledDesc;
|
||||
extern string_view mp_SharedProgressDesc;
|
||||
extern string_view mp_SyncIdDesc;
|
||||
extern string_view mp_SharedHealthDesc;
|
||||
extern string_view mp_SharedRupeesDesc;
|
||||
extern string_view mp_SharedAmmoDesc;
|
||||
|
||||
extern string_view zTargetingDesc;
|
||||
extern string_view cameraControlDesc;
|
||||
extern string_view motionControlDesc;
|
||||
extern string_view togglePlayMusicDesc;
|
||||
extern string_view togglePlaySFXDesc;
|
||||
extern string_view silenceNaviDesc;
|
||||
extern string_view ignoreMaskReactionDesc;
|
||||
|
||||
extern string_view naviColorsDesc;
|
||||
extern string_view necessarySimpleModeDesc;
|
||||
extern string_view alwaysSimpleModeDesc;
|
||||
|
||||
extern string_view coloredKeysDesc;
|
||||
extern string_view coloredBossKeysDesc;
|
||||
|
||||
extern string_view mirrorWorldDesc;
|
||||
|
||||
extern string_view musicRandoDesc;
|
||||
extern string_view shuffleBGMDesc;
|
||||
extern string_view fanfaresOffDesc;
|
||||
extern string_view onlyFanfaresDesc;
|
||||
extern string_view fanfaresOcarinaDesc;
|
||||
extern string_view shuffleOcaMusicDesc;
|
||||
|
||||
extern string_view shuffleSFXOff;
|
||||
extern string_view shuffleSFXAll;
|
||||
extern string_view shuffleSFXSceneSpecific;
|
||||
extern string_view shuffleSFXChaos;
|
||||
extern string_view shuffleSFXCategorically;
|
||||
|
||||
extern string_view randomTrapDmgDesc;
|
||||
extern string_view basicTrapDmgDesc;
|
||||
extern string_view advancedTrapDmgDesc;
|
||||
|
||||
extern string_view ToggleAllTricksDesc;
|
||||
|
||||
extern string_view ToggleLogicNoneDesc;
|
||||
extern string_view ToggleLogicNoviceDesc;
|
||||
extern string_view ToggleLogicIntermediateDesc;
|
||||
extern string_view ToggleLogicExpertDesc;
|
||||
extern string_view LogicGrottosWithoutAgonyDesc;
|
||||
extern string_view LogicVisibleCollisionDesc;
|
||||
extern string_view LogicFewerTunicRequirementsDesc;
|
||||
extern string_view LogicLostWoodsGSBeanDesc;
|
||||
extern string_view LogicLabDivingDesc;
|
||||
extern string_view LogicLabWallGSDesc;
|
||||
extern string_view LogicGraveyardPoHDesc;
|
||||
extern string_view LogicChildDampeRacePoHDesc;
|
||||
extern string_view LogicGVHammerChestDesc;
|
||||
extern string_view LogicGerudoKitchenDesc;
|
||||
extern string_view LogicLensWastelandDesc;
|
||||
extern string_view LogicReverseWastelandDesc;
|
||||
extern string_view LogicColossusGSDesc;
|
||||
extern string_view LogicOutsideGanonsGSDesc;
|
||||
extern string_view LogicManOnRoofDesc;
|
||||
extern string_view LogicWindmillPoHHookshotDesc;
|
||||
extern string_view LogicDMTBombableDesc;
|
||||
extern string_view LogicDMTSoilGSDesc;
|
||||
extern string_view LogicDMTSummitHoverDesc;
|
||||
extern string_view LogicLinkGoronDinsDesc;
|
||||
extern string_view LogicGoronCityLeftMostDesc;
|
||||
extern string_view LogicGoronCityPotDesc;
|
||||
extern string_view LogicGoronCityPotWithStrengthDesc;
|
||||
extern string_view LogicChildRollingWithStrengthDesc;
|
||||
extern string_view LogicCraterUpperToLowerDesc;
|
||||
extern string_view LogicCraterBeanPoHWithHoversDesc;
|
||||
extern string_view LogicBiggoronBoleroDesc;
|
||||
extern string_view LogicZoraRiverLowerDesc;
|
||||
extern string_view LogicZoraRiverUpperDesc;
|
||||
extern string_view LogicZFGreatFairyDesc;
|
||||
extern string_view LogicDekuB1WebsWithBowDesc;
|
||||
extern string_view LogicDekuB1SkipDesc;
|
||||
extern string_view LogicDekuBasementGSDesc;
|
||||
extern string_view LogicDCStaircaseDesc;
|
||||
extern string_view LogicDCJumpDesc;
|
||||
extern string_view LogicDCSlingshotSkipDesc;
|
||||
extern string_view LogicDCScarecrowGSDesc;
|
||||
extern string_view LogicJabuBossGSAdultDesc;
|
||||
extern string_view LogicJabuScrubJumpDiveDesc;
|
||||
extern string_view LogicForestOutsideBackdoorDesc;
|
||||
extern string_view LogicForestDoorFrameDesc;
|
||||
extern string_view LogicForestOutdoorEastGSDesc;
|
||||
extern string_view LogicFireBossDoorJumpDesc;
|
||||
extern string_view LogicFireStrengthDesc;
|
||||
extern string_view LogicFireScarecrowDesc;
|
||||
extern string_view LogicFireFlameMazeDesc;
|
||||
extern string_view LogicFireSongOfTimeDesc;
|
||||
extern string_view LogicWaterTempleTorchLongshotDesc;
|
||||
extern string_view LogicWaterTempleUpperBoostDesc;
|
||||
extern string_view LogicWaterCentralBowDesc;
|
||||
extern string_view LogicWaterCentralGSFWDesc;
|
||||
extern string_view LogicWaterCrackedWallNothingDesc;
|
||||
extern string_view LogicWaterCrackedWallHoversDesc;
|
||||
extern string_view LogicWaterBossKeyRegionDesc;
|
||||
extern string_view LogicWaterBKJumpDiveDesc;
|
||||
extern string_view LogicWaterNorthBasementLedgeJumpDesc;
|
||||
extern string_view LogicWaterDragonAdultDesc;
|
||||
extern string_view LogicWaterDragonJumpDiveDesc;
|
||||
extern string_view LogicWaterRiverGSDesc;
|
||||
extern string_view LogicWaterFallingPlatformGSDesc;
|
||||
extern string_view LogicSpiritLowerAdultSwitchDesc;
|
||||
extern string_view LogicSpiritChildBombchuDesc;
|
||||
extern string_view LogicSpiritWallDesc;
|
||||
extern string_view LogicSpiritLobbyGSDesc;
|
||||
extern string_view LogicSpiritMapChestDesc;
|
||||
extern string_view LogicSpiritSunChestDesc;
|
||||
extern string_view LogicShadowFireArrowEntryDesc;
|
||||
extern string_view LogicShadowUmbrellaDesc;
|
||||
extern string_view LogicShadowFreestandingKeyDesc;
|
||||
extern string_view LogicShadowStatueDesc;
|
||||
extern string_view LogicChildDeadhandDesc;
|
||||
extern string_view LogicGtgWithoutHookshotDesc;
|
||||
extern string_view LogicGtgFakeWallDesc;
|
||||
extern string_view LogicLensSpiritDesc;
|
||||
extern string_view LogicLensShadowDesc;
|
||||
extern string_view LogicLensShadowBackDesc;
|
||||
extern string_view LogicLensBotwDesc;
|
||||
extern string_view LogicLensGtgDesc;
|
||||
extern string_view LogicLensCastleDesc;
|
||||
extern string_view LogicLensJabuMQDesc;
|
||||
extern string_view LogicLensSpiritMQDesc;
|
||||
extern string_view LogicLensShadowMQDesc;
|
||||
extern string_view LogicLensShadowMQBackDesc;
|
||||
extern string_view LogicLensBotwMQDesc;
|
||||
extern string_view LogicLensGtgMQDesc;
|
||||
extern string_view LogicLensCastleMQDesc;
|
||||
extern string_view LogicSpiritTrialHookshotDesc;
|
||||
extern string_view LogicFlamingChestsDesc;
|
||||
|
||||
extern const std::vector<string_view> GlitchDifficulties;
|
||||
|
||||
extern string_view GlitchRestrictedItemsDescDisabled;
|
||||
extern string_view GlitchRestrictedItemsDescNovice;
|
||||
|
||||
extern string_view GlitchSuperStabDescDisabled;
|
||||
extern string_view GlitchSuperStabDescNovice;
|
||||
|
||||
extern string_view GlitchISGDescDisabled;
|
||||
extern string_view GlitchISGDescNovice;
|
||||
extern string_view GlitchISGDescIntermediate;
|
||||
extern string_view GlitchISGDescAdvanced;
|
||||
|
||||
extern string_view GlitchHoverDescDisabled;
|
||||
extern string_view GlitchHoverDescNovice;
|
||||
extern string_view GlitchHoverDescIntermediate;
|
||||
extern string_view GlitchHoverDescAdvanced;
|
||||
|
||||
extern string_view GlitchBombOIDescDisabled;
|
||||
extern string_view GlitchBombOIDescNovice;
|
||||
extern string_view GlitchBombOIDescIntermediate;
|
||||
extern string_view GlitchBombOIDescAdvanced;
|
||||
extern string_view GlitchBombOIDescExpert;
|
||||
|
||||
extern string_view GlitchHoverBoostDescDisabled;
|
||||
extern string_view GlitchHoverBoostDescNovice;
|
||||
extern string_view GlitchHoverBoostDescIntermediate;
|
||||
extern string_view GlitchHoverBoostDescAdvanced;
|
||||
|
||||
extern string_view GlitchSuperSlideDescDisabled;
|
||||
extern string_view GlitchSuperSlideDescNovice;
|
||||
extern string_view GlitchSuperSlideDescIntermediate;
|
||||
extern string_view GlitchSuperSlideDescAdvanced;
|
||||
extern string_view GlitchSuperSlideDescExpert;
|
||||
|
||||
extern string_view GlitchMegaflipDescDisabled;
|
||||
extern string_view GlitchMegaflipDescNovice;
|
||||
extern string_view GlitchMegaflipDescIntermediate;
|
||||
extern string_view GlitchMegaflipDescAdvanced;
|
||||
extern string_view GlitchMegaflipDescExpert;
|
||||
extern string_view GlitchMegaflipDescHero;
|
||||
|
||||
extern string_view GlitchASlideDescDisabled;
|
||||
extern string_view GlitchASlideDescNovice;
|
||||
extern string_view GlitchASlideDescIntermediate;
|
||||
extern string_view GlitchASlideDescAdvanced;
|
||||
extern string_view GlitchASlideDescExpert;
|
||||
|
||||
extern string_view GlitchHammerSlideDescDisabled;
|
||||
extern string_view GlitchHammerSlideDescNovice;
|
||||
extern string_view GlitchHammerSlideDescIntermediate;
|
||||
|
||||
extern string_view GlitchLedgeCancelDescDisabled;
|
||||
extern string_view GlitchLedgeCancelDescNovice;
|
||||
extern string_view GlitchLedgeCancelDescIntermediate;
|
||||
extern string_view GlitchLedgeCancelDescAdvanced;
|
||||
|
||||
extern string_view GlitchActionSwapDescDisabled;
|
||||
extern string_view GlitchActionSwapDescNovice;
|
||||
extern string_view GlitchActionSwapDescAdvanced;
|
||||
|
||||
extern string_view GlitchQPADescDisabled;
|
||||
extern string_view GlitchQPADescNovice;
|
||||
extern string_view GlitchQPADescIntermediate;
|
||||
extern string_view GlitchQPADescAdvanced;
|
||||
extern string_view GlitchQPADescExpert;
|
||||
|
||||
extern string_view GlitchHookshotClipDescDisabled;
|
||||
extern string_view GlitchHookshotClipDescNovice;
|
||||
extern string_view GlitchHookshotClipDescIntermediate;
|
||||
|
||||
extern string_view GlitchHookshotJump_BonkDescDisabled;
|
||||
extern string_view GlitchHookshotJump_BonkDescNovice;
|
||||
extern string_view GlitchHookshotJump_BonkDescIntermediate;
|
||||
extern string_view GlitchHookshotJump_BonkDescAdvanced;
|
||||
|
||||
extern string_view GlitchHookshotJump_BootsDescDisabled;
|
||||
extern string_view GlitchHookshotJump_BootsDescNovice;
|
||||
extern string_view GlitchHookshotJump_BootsDescIntermediate;
|
||||
extern string_view GlitchHookshotJump_BootsDescAdvanced;
|
||||
|
||||
extern string_view GlitchCutsceneDiveDescDisabled;
|
||||
extern string_view GlitchCutsceneDiveDescNovice;
|
||||
extern string_view GlitchCutsceneDiveDescIntermediate;
|
||||
extern string_view GlitchCutsceneDiveDescAdvanced;
|
||||
|
||||
extern string_view GlitchNaviDive_StickDescDisabled;
|
||||
extern string_view GlitchNaviDive_StickDescNovice;
|
||||
extern string_view GlitchNaviDive_StickDescIntermediate;
|
||||
extern string_view GlitchNaviDive_StickDescAdvanced;
|
||||
|
||||
extern string_view GlitchTripleSlashClipDescDisabled;
|
||||
extern string_view GlitchTripleSlashClipDescNovice;
|
||||
extern string_view GlitchTripleSlashClipDescIntermediate;
|
||||
extern string_view GlitchTripleSlashClipDescAdvanced;
|
||||
extern string_view GlitchTripleSlashClipDescExpert;
|
||||
|
||||
extern string_view GlitchLedgeClipDescDisabled;
|
||||
extern string_view GlitchLedgeClipDescNovice;
|
||||
extern string_view GlitchLedgeClipDescIntermediate;
|
||||
extern string_view GlitchLedgeClipDescAdvanced;
|
||||
|
||||
extern string_view GlitchSeamWalkDescDisabled;
|
||||
extern string_view GlitchSeamWalkDescNovice;
|
||||
extern string_view GlitchSeamWalkDescIntermediate;
|
||||
extern string_view GlitchSeamWalkDescAdvanced;
|
||||
extern string_view GlitchSeamWalkDescExpert;
|
||||
extern string_view GlitchSeamWalkDescHero;
|
||||
|
||||
extern string_view GlitchWWTEscapeDesc;
|
||||
extern string_view GlitchGVTentAsChildDesc;
|
||||
extern string_view GlitchGFGuardSneakDesc;
|
||||
extern string_view GlitchItemlessWastelandDesc;
|
||||
extern string_view GlitchOccamsStatueDesc;
|
||||
extern string_view GlitchZDOoBJumpSlashDesc;
|
||||
extern string_view GlitchJabuStickRecoilDesc;
|
||||
extern string_view GlitchJabuAdultDesc;
|
||||
extern string_view GlitchBlueFireWallDesc;
|
||||
extern string_view GlitchClassicHalfieDesc;
|
||||
extern string_view GlitchModernHalfieDesc;
|
||||
extern string_view GlitchJabuSwitchDesc;
|
||||
extern string_view GlitchForestBKSkipDesc;
|
||||
extern string_view GlitchFireGrunzClipDesc;
|
2779
soh/soh/Enhancements/randomizer/3drando/settings.cpp
Normal file
2779
soh/soh/Enhancements/randomizer/3drando/settings.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1282
soh/soh/Enhancements/randomizer/3drando/settings.hpp
Normal file
1282
soh/soh/Enhancements/randomizer/3drando/settings.hpp
Normal file
File diff suppressed because it is too large
Load Diff
735
soh/soh/Enhancements/randomizer/3drando/shops.cpp
Normal file
735
soh/soh/Enhancements/randomizer/3drando/shops.cpp
Normal file
@ -0,0 +1,735 @@
|
||||
#include "item_location.hpp"
|
||||
#include "item_pool.hpp"
|
||||
#include "location_access.hpp"
|
||||
#include "random.hpp"
|
||||
#include "item.hpp"
|
||||
#include "shops.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <math.h>
|
||||
#include <map>
|
||||
#include "z64item.h"
|
||||
|
||||
using namespace Settings;
|
||||
|
||||
std::vector<ItemAndPrice> NonShopItems = {};
|
||||
|
||||
static std::array<std::array<Text, 3>, 0xD5> trickNameTable; //Table of trick names for ice traps
|
||||
bool initTrickNames = false; //Indicates if trick ice trap names have been initialized yet
|
||||
|
||||
//Set vanilla shop item locations before potentially shuffling
|
||||
void PlaceVanillaShopItems() {
|
||||
//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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//These are the vanilla shop items, but in a priority order of importance
|
||||
//However many shop item slots were cleared, this will return 64 minus that number of vanilla shop items to be placed with assumed fill
|
||||
//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_5,
|
||||
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,
|
||||
//^First 28 items from OoTR
|
||||
BUY_HYLIAN_SHIELD,
|
||||
BUY_BOTTLE_BUG,
|
||||
BUY_DEKU_STICK_1,
|
||||
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,
|
||||
//^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,
|
||||
//^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,
|
||||
//^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,
|
||||
//^All 64 items: Only exist with shopsanity 0
|
||||
};
|
||||
//Now delete however many items there are to replace
|
||||
for (int i = 0; i < total_replaced; i++) {
|
||||
minShopItems.pop_back();
|
||||
}
|
||||
return minShopItems;
|
||||
}
|
||||
|
||||
//This table contains a cumulative probability for each possible shop price based on
|
||||
// a beta distribution with alpha = 1.5, beta = 2, and the result of the distribution, a float in [0.0, 1.0),
|
||||
// being mutliplied by 60, casted to an integer, then multiplied by 5 to give a value in range [0, 295] in increments of 5.
|
||||
// Meaning the first value is the probability of 0, the next value is the probability of 0 plus the probability of 5, etc.
|
||||
//Probabilities generated using a python script with 1 billion trials, so should hopefully be pretty good
|
||||
//Average price ~126
|
||||
//~38% chance of needing no wallet, ~45% chance of needing 1, ~17% chance of needing 2
|
||||
static constexpr std::array<double, 60> ShopPriceProbability= {
|
||||
0.005326994, 0.014908518, 0.027114719, 0.041315285, 0.057136304, 0.074325887, 0.092667151, 0.112002061, 0.132198214, 0.153125390,
|
||||
0.174696150, 0.196810540, 0.219388148, 0.242361379, 0.265657012, 0.289205134, 0.312970402, 0.336877590, 0.360881110, 0.384932772,
|
||||
0.408976198, 0.432982176, 0.456902494, 0.480686053, 0.504313389, 0.527746488, 0.550938554, 0.573856910, 0.596465330, 0.618736235,
|
||||
0.640646600, 0.662162782, 0.683240432, 0.703859801, 0.724001242, 0.743631336, 0.762722631, 0.781259986, 0.799198449, 0.816521905,
|
||||
0.833208595, 0.849243398, 0.864579161, 0.879211177, 0.893112051, 0.906263928, 0.918639420, 0.930222611, 0.940985829, 0.950914731,
|
||||
0.959992180, 0.968187000, 0.975495390, 0.981884488, 0.987344345, 0.991851853, 0.995389113, 0.997937921, 0.999481947, 1.000000000,
|
||||
};
|
||||
int GetRandomShopPrice() {
|
||||
double random = RandomDouble(); //Randomly generated probability value
|
||||
for (size_t i = 0; i < ShopPriceProbability.size(); i++) {
|
||||
if (random < ShopPriceProbability[i]) {
|
||||
//The randomly generated value has surpassed the total probability up to this point, so this is the generated price
|
||||
return i * 5; //i in range [0, 59], output in range [0, 295] in increments of 5
|
||||
}
|
||||
}
|
||||
return -1; //Shouldn't happen
|
||||
}
|
||||
|
||||
//Similar to above, beta distribution with alpha = 1, beta = 2,
|
||||
// multiplied by 20 instead of 60 to give values in rage [0, 95] in increments of 5
|
||||
//Average price ~31
|
||||
static constexpr std::array<double, 20> ScrubPriceProbability = {
|
||||
0.097500187, 0.190002748, 0.277509301, 0.360018376, 0.437522571, 0.510021715, 0.577520272, 0.640029304, 0.697527584, 0.750024535,
|
||||
0.797518749, 0.840011707, 0.877508776, 0.910010904, 0.937504342, 0.960004661, 0.977502132, 0.989998967, 0.997500116, 1.000000000,
|
||||
};
|
||||
|
||||
int16_t GetRandomScrubPrice() {
|
||||
double random = RandomDouble();
|
||||
for (size_t i = 0; i < ScrubPriceProbability.size(); i++) {
|
||||
if (random < ScrubPriceProbability[i]) {
|
||||
return i * 5; // i in range [0, 19], output in range [0, 95] in increments of 5
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Get 1 to 4, or a random number from 1-4 depending on shopsanity setting
|
||||
int GetShopsanityReplaceAmount() {
|
||||
if (Settings::Shopsanity.Is(SHOPSANITY_ONE)) {
|
||||
return 1;
|
||||
} else if (Settings::Shopsanity.Is(SHOPSANITY_TWO)) {
|
||||
return 2;
|
||||
} else if (Settings::Shopsanity.Is(SHOPSANITY_THREE)) {
|
||||
return 3;
|
||||
} else if (Settings::Shopsanity.Is(SHOPSANITY_FOUR)) {
|
||||
return 4;
|
||||
} else { //Random, get number in [1, 4]
|
||||
return Random(1, 5);
|
||||
}
|
||||
}
|
||||
|
||||
//Initialize the table of trick names with an easy, medium, and hard name for each language
|
||||
void InitTrickNames() {
|
||||
trickNameTable[GI_SWORD_KOKIRI] = {
|
||||
Text{"Korok Sword", "Épée Korok", "Espada Korok"},
|
||||
Text{"Hero's Sword", "Épée du Héros", "Espada del héroe"},
|
||||
Text{"Razor Sword", "Lame Rasoir", "Espada de esmeril"}};
|
||||
/* trickNameTable[GI_SWORD_MASTER] = {
|
||||
Text{"Goddess Sword", "Épée de la déesse", "Espada Divina"},
|
||||
Text{"Gilded Sword", "Excalibur", "Espada de los Sabios"},
|
||||
Text{"Magical Sword", "Lame dorée", "Fay"}};*/
|
||||
trickNameTable[GI_SWORD_KNIFE] = {
|
||||
Text{"Big Goron's Sword", "Épée de Gros Goron", "Espada de Big Goron"},
|
||||
Text{"Fierce Deity's Sword", "Épée du Dieu Démon", "Espada de la Fiera Deidad"},
|
||||
Text{"Biggoron's Knife", "Lame de Grogoron", "Daga de Biggoron"}};
|
||||
trickNameTable[GI_SWORD_BGS] = {
|
||||
Text{"Big Goron's Sword", "Épée de Biggoron", "Espada de Big Goron"},
|
||||
Text{"Fierce Deity's Sword", "Épée du dieu démon", "Espada de la Fiera Deidad"},
|
||||
Text{"Biggoron's Knife", "Lame de Grogoron", "Daga de Biggoron"}};
|
||||
trickNameTable[GI_SHIELD_DEKU] = {
|
||||
Text{"Boko Shield", "Bouclier Boko", "Escudo Boko"},
|
||||
Text{"Ordon Shield", "Bouclier de Toal", "Escudo de Ordon"},
|
||||
Text{"Wooden Shield", "Bouclier de Bois", "Escudo de madera"}};
|
||||
trickNameTable[GI_SHIELD_HYLIAN] = {
|
||||
Text{"Hyrule Shield", "Bouclier d'Hyrule", "Escudo Hylian"},
|
||||
Text{"Goddess Shield", "Bouclier Sacré", "Escudo Divino"},
|
||||
Text{"Hero's Shield", "Bouclier du Héros", "Escudo del héroe"}};
|
||||
trickNameTable[GI_SHIELD_MIRROR] = {
|
||||
Text{"Magic Mirror", "Miroir Magique", "Escudo mágico"},
|
||||
Text{"Magical Shield", "Bouclier Magique", "Escudo arcano"},
|
||||
Text{"Mirror of Twilight", "Miroir des Ombres", "Espejo del Crepúsculo"}};
|
||||
trickNameTable[GI_TUNIC_GORON] = {
|
||||
Text{"Gerudo Tunic", "Tunique Gerudo", "Sayo gerudo"},
|
||||
Text{"Magic Armor", "Armure Magique", "Túnica Goron"},
|
||||
Text{"Red Mail", "Habits Rouges", "Ropas rojas"}};
|
||||
trickNameTable[GI_TUNIC_ZORA] = {
|
||||
Text{"Rito Tunic", "Tunique Rito", "Sayo rito"},
|
||||
Text{"Zora Armor", "Armure Zora", "Túnica Zora"},
|
||||
Text{"Blue Mail", "Habits Bleus", "Ropas azules"}};
|
||||
trickNameTable[GI_BOOTS_IRON] = {
|
||||
Text{"Iron Hoofs", "Patins de Plomb", "Botas férreas"},
|
||||
Text{"Snow Boots", "Bottes de Neige", "Botas de nieve"},
|
||||
Text{"Boots of Power", "Bottes de Puissance", "Botas de plomo"}};
|
||||
trickNameTable[GI_BOOTS_HOVER] = {
|
||||
Text{"Hover Hoofs", "Patins des airs", "Botas flotadoras"},
|
||||
Text{"Pegasus Boots", "Bottes pégase", "Botas de Pegaso"},
|
||||
Text{"Boots of Speed", "Bottes de vitesse", "Botas del desierto"}};
|
||||
trickNameTable[GI_WEIRD_EGG] = {
|
||||
Text{"Poached Egg", "Oeuf à la coque", "Huevo pasado"},
|
||||
Text{"Lon Lon Egg", "Oeuf Lon Lon", "Huevo Lon Lon"},
|
||||
Text{"Zora Egg", "Oeuf Zora", "Huevo Zora"}};
|
||||
trickNameTable[GI_LETTER_ZELDA] = {
|
||||
Text{"Ruto's Letter", "Lettre de Ruto", "Carta de Ruto"},
|
||||
Text{"Royal Letter", "Lettre Eoyale", "Carta para Kafei"},
|
||||
Text{"Zelda's Business Card", "Carte d'affaires de Zelda", "Carta"}};
|
||||
trickNameTable[GI_BOOMERANG] = {
|
||||
Text{"Prank Fetch Toy", "Inséparable Bâtonnet", "Bumerang"},
|
||||
Text{"Gale Boomerang", "Boomerang Tornade", "Bumerán tornado"},
|
||||
Text{"Magic Boomerang", "Boomerang Magique", "Bumerán mágico"}};
|
||||
trickNameTable[GI_LENS] = {
|
||||
Text{"Sheikah-leidoscope", "Sheikah-léidoscope", "Monóculo de la Verdad"},
|
||||
Text{"Sheikah Sensor", "Sonar Sheikah", "Sensor Sheikah"},
|
||||
Text{"Magnifying Lens", "Loupe", "Lente Aumentadora"}};
|
||||
trickNameTable[GI_HAMMER] = {
|
||||
Text{"Goron Gavel", "Masse Perforatrice", "Mazo Goron"},
|
||||
Text{"Magic Hammer", "Marteau Magique", "Martillo mágico"},
|
||||
Text{"Skull Hammer", "Maillet Ressort", "Martillo de hierro"}};
|
||||
trickNameTable[GI_STONE_OF_AGONY] = {
|
||||
Text{"Shard of Agahnim", "Fragment d'Agahnim", "Piedra de Agahnim"},
|
||||
Text{"Stone of Agony", "Pierre de Souffrance", "Fragmento de la Agonía"},
|
||||
Text{"Pirate's Charm", "Pierre de Pirate", "Amuleto Pirata"}};
|
||||
trickNameTable[GI_DINS_FIRE] = {
|
||||
Text{"Eldin's Fire", "Feu d'Eldin", "Fuego de Eldin"},
|
||||
Text{"Din's Blaze", "Flamme de Din", "Poder de Din"},
|
||||
Text{"Din's Pearl", "Perle de Din", "Orbe de Din"}};
|
||||
trickNameTable[GI_FARORES_WIND] = {
|
||||
Text{"Faron's Wind", "Vent de Firone", "Viento de Farone"},
|
||||
Text{"Farore's Windfall", "Zéphyr de Farore", "Valor de Farore"},
|
||||
Text{"Farore's Pearl", "Perle de Farore", "Orbe de Farore"}};
|
||||
trickNameTable[GI_NAYRUS_LOVE] = {
|
||||
Text{"Lanayru's Love", "Amour de Lanelle", "Amor de Lanayru"},
|
||||
Text{"Nayru's Passion", "Passion de Nayru", "Sabiduría de Nayru"},
|
||||
Text{"Nayru's Pearl", "Perle de Nayru", "Orbe de Nayru"}};
|
||||
trickNameTable[GI_ARROW_FIRE] = {
|
||||
Text{"Soul Arrow", "Flèche des Esprits", "Flecha del Espíritu"},
|
||||
Text{"Bomb Arrow", "Flèche-Bombe", "Flecha bomba"},
|
||||
Text{"Fire Candy", "Bonbon deFfeu", "Cetro de fuego"}};
|
||||
trickNameTable[GI_ARROW_ICE] = {
|
||||
Text{"Shadow Arrow", "Flèche d'Ombre", "Flecha de las Sombras"},
|
||||
Text{"Ancient Arrow", "Flèche Archéonique", "Flecha ancestral"},
|
||||
Text{"Ice Trap Arrow", "Flèche de Piège de Glace", "Cetro de hielo"}};
|
||||
trickNameTable[GI_ARROW_LIGHT] = {
|
||||
Text{"Wind Arrow", "Flèche de Vent", "Flecha del Viento"},
|
||||
Text{"Shock Arrow", "Flèches Électriques", "Flecha eléctrica"},
|
||||
Text{"Silver Arrow", "Flèches d'Argent", "Flecha de plata"}};
|
||||
trickNameTable[GI_GERUDO_CARD] = {
|
||||
Text{"Desert Title Deed", "Abonnement Gerudo", "Escritura del desierto"},
|
||||
Text{"Gerudo's Card", "Carte Goron", "Tóken Gerudo"},
|
||||
Text{"Gerudo's Membership Card", "Autographe de Nabooru", "Tarjeta Gerudo"}};
|
||||
|
||||
trickNameTable[0xC9] = {
|
||||
Text{"Funky Bean Pack", "Paquet de Fèves Magiques", "Lote de frijoles mágicos"},
|
||||
Text{"Crenel Bean Pack", "Paquet de Haricots Gonggle", "Lote de alubias mágicas"},
|
||||
Text{"Mystic Bean Pack", "Paquet de Haricots Mystiques", "Lote de porotos mágicos"}};
|
||||
trickNameTable[0xB8] = {
|
||||
Text{"Diamond Hearts", "Coeurs de Diamant", "Contenedor de diamante"},
|
||||
Text{"Double Damage", "Double Souffrance", "Doble daño receptivo"},
|
||||
Text{"Quadruple Defence", "Quadruple Défence", "Defensa cuádruple"}};
|
||||
|
||||
trickNameTable[GI_POCKET_EGG] = {
|
||||
Text{"Poached Egg", "oeuf à la coque", "Huevo pasado"},
|
||||
Text{"Lon Lon Egg", "oeuf Lon Lon", "Huevo Lon Lon"},
|
||||
Text{"Zora Egg", "oeuf Zora", "Huevo del Pez Viento"}};
|
||||
trickNameTable[GI_POCKET_CUCCO] = {
|
||||
Text{"D.I.Y. Alarm Clock", "Réveille-matin improvisé", "Alarma emplumada portátil"},
|
||||
Text{"Kakariko Cucco", "Cocotte Cocorico", "Cuco de Kakariko"},
|
||||
Text{"Hatched Cucco", "Cocotte éclose", "Pollo de bolsillo"}};
|
||||
trickNameTable[GI_COJIRO] = {
|
||||
Text{"Blucco", "Chair-Qui-Poule", "Cucazul"},
|
||||
Text{"Grog's Cucco", "Cocotte de Grog", "Cuco de Grog"},
|
||||
Text{"Corijo", "Cojiro", "Corijo"}};
|
||||
trickNameTable[GI_ODD_MUSHROOM] = {
|
||||
Text{"Magic Mushroom", "Champignon magique", "Champiñón mágico"},
|
||||
Text{"Endura Shroom", "Champi Vigueur", "Champiñón del bosque"},
|
||||
Text{"Mushroom", "Champignon", "Seta"}};
|
||||
trickNameTable[GI_ODD_POTION] = {
|
||||
Text{"Odd Medicine", "Élixir suspect", "Poción rara"},
|
||||
Text{"Granny's Poultice", "Mixture de Granny", "Medicina de la abuela"},
|
||||
Text{"Mushroom Poultice", "Mixture de champignon", "Medicina de champiñones"}};
|
||||
trickNameTable[GI_SAW] = {
|
||||
Text{"Carpenter's Saw", "Scie du charpentier", "Sierra del carpintero"},
|
||||
Text{"Poacher's Sword", "Hache du chasseur", "Espada del capataz"},
|
||||
Text{"Grog's Saw", "Scie de Grog", "Sierra del Cazador Furtivo"}};
|
||||
trickNameTable[GI_SWORD_BROKEN] = {
|
||||
Text{"Broken Biggoron's Sword", "Épée brisée de Grogoron", "Espada de Biggoron rota"},
|
||||
Text{"Broken Giant's Knife", "Lame des Géants brisée", "Daga gigante rota"},
|
||||
Text{"Biggoron's Sword", "Épée de Biggoron", "Espada de Biggoron"}};
|
||||
trickNameTable[GI_PRESCRIPTION] = {
|
||||
Text{"Biggoron's Prescription", "Ordonnance de Grogoron", "Receta de Biggoron"},
|
||||
Text{"Eyedrop Prescription", "Ordonnance de gouttes", "Receta ocular"},
|
||||
Text{"Urgent Prescription", "Ordonnance urgente", "Prescripción"}};
|
||||
trickNameTable[GI_FROG] = {
|
||||
Text{"Don Gero", "Don Gero", "Don Gero"},
|
||||
Text{"Eyedrop Frog", "Grenouille-qui-louche", "Globo Ocular de Rana"},
|
||||
Text{"Frog", "Crapaud", "Rana"}};
|
||||
trickNameTable[GI_EYEDROPS] = {
|
||||
Text{"Biggoron's Eyedrops", "Gouttes de Grogoron", "Gotas de Biggoron"},
|
||||
Text{"Hyrule's Finest Eyedrops", "Eau du Lac Hylia", "Gotas oculares"},
|
||||
Text{"Zora Perfume", "Parfum Zora", "Perfume Zora"}};
|
||||
trickNameTable[GI_CLAIM_CHECK] = {
|
||||
Text{"Clay Check", "Certificat Grogoron", "Comprobante de Reclamación"},
|
||||
Text{"Sheikah Slate", "Tablette Sheikah", "Piedra Sheikah"},
|
||||
Text{"Cyclone Slate", "Ardoise des tornades", "Pizarra de los Torbellinos"}};
|
||||
|
||||
trickNameTable[GI_SKULL_TOKEN] = {
|
||||
Text{"Skulltula Token", "Bon de Skulltula dorée", "Símbolo de Skulltula"},
|
||||
Text{"Golden Skulltula Spirit", "Pièce de Skulltula dorée", "Tóken de Skulltula Dorada"},
|
||||
Text{"Gold Walltula Token", "Jeton de Walltula dorée", "Skulltula dorada"}};
|
||||
|
||||
trickNameTable[0x80] = {
|
||||
Text{"Progressive Grappling Hook", "Lance-chaîne (prog.)", "Garra progresiva"},
|
||||
Text{"Progressive Clawshot", "Grappin-griffe (prog.)", "Zarpa progresiva"},
|
||||
Text{"Progressive Gripshot", "Grappince (prog.)", "Enganchador progresivo"}};
|
||||
trickNameTable[0x81] = {
|
||||
Text{"Progressive Glove", "Gant de puissance (prog.)", "Guanteletes progresivos"},
|
||||
Text{"Progressive Power Bracelet", "Bracelet de force (prog.)", "Brasaletes progresivos"},
|
||||
Text{"Progressive Magic Bracelet", "Bracelet magique (prog.)", "Manoplas progresivas"}};
|
||||
trickNameTable[0x82] = {
|
||||
Text{"Progressive Bomb Capacity", "Capacité de bombes (prog.)", "Mayor capacidad de bombas"},
|
||||
Text{"Progressive Bomb Pack", "Paquet de bombes (prog.)", "Zurrón de bombas progresivo"},
|
||||
Text{"Progressive Bomb Box", "Boîte à bombes (prog.)", "Bolsa de bombas progresiva"}};
|
||||
trickNameTable[0x83] = {
|
||||
Text{"Progressive Arrow Capacity", "Capacité de flèches (prog.)", "Mayor capacidad de flechas"},
|
||||
Text{"Progressive Hero's Bow", "Arc du héros (prog.)", "Arco del héroe progresivo"},
|
||||
Text{"Progressive Arrow Holder", "Arbalète (prog.)", "Ballesta progresiva"}};
|
||||
trickNameTable[0x84] = {
|
||||
Text{"Progressive Seed Capacity", "Capacité de graines (prog.)", "Mayor capacidad de semillas"},
|
||||
Text{"Progressive Scattershot", "Lance-Pierre rafale (prog.)", "Resortera múltiple progresiva"},
|
||||
Text{"Progressive Seed Satchel", "Sac de graines (prog.)", "Bolsa de semillas progresiva"}};
|
||||
trickNameTable[0x85] = {
|
||||
Text{"Progressive Rupee Capacity", "Capacité de rubis (prog.)", "Mayor capacidad de rupias"},
|
||||
Text{"Progressive Purse", "Sacoche (prog.)", "Cartera de rupias progresiva"},
|
||||
Text{"Progressive Rupee Bag", "Sac à rubis (prog.)", "Zurrón de rupias progresivo"}};
|
||||
trickNameTable[0x86] = {
|
||||
Text{"Progressive Diving Ability", "Plongée (prog.)", "Buceo progresivo"},
|
||||
Text{"Progressive Pearl", "Perle (prog.)", "Perla progresiva"},
|
||||
Text{"Progressive Scute", "Bulle (prog.)", "Fragmento Zora progresivo"}};
|
||||
trickNameTable[0x87] = {
|
||||
Text{"Progressive Nut Pack", "Paquet de noix (prog.)", "Mayor capacidad de semillas"},
|
||||
Text{"Progressive Nut Bag", "Sac de noix (prog.)", "Bolsa de nueces progresiva"},
|
||||
Text{"Progressive Husk Capacity", "Capacité de noisettes (prog.)", "Mayor capacidad de castañas"}};
|
||||
trickNameTable[0x88] = {
|
||||
Text{"Progressive Stick Pack", "Paquet de bâtons Mojo (prog.)", "Mayor capacidad de bastones"},
|
||||
Text{"Progressive Stick Bag", "Sac de bâtons (prog.)", "Mayor capacidad de ramas deku"},
|
||||
Text{"Progressive Rod Capacity", "Capacité de tiges (prog.)", "Mayor capacidad de cetros deku"}};
|
||||
trickNameTable[0x89] = {
|
||||
Text{"Progressive Bomblings", "Bombinsectes (prog.)", "Bombinsectos progresivos"},
|
||||
Text{"Progressive Missiles", "Missiles (prog.)", "Misiles progresivos"},
|
||||
Text{"Progressive Bombchu Bag", "Sac à Bombchu (prog.)", "Bombachus progresivos"}};
|
||||
trickNameTable[0x8A] = {
|
||||
Text{"Progressive Stamina Meter", "Jauge d'endurance (prog.)", "Medidor de vigor progresivo"},
|
||||
Text{"Progressive Energy Meter", "Jauge d'énergie (prog.)", "Medidor de energía progresivo"},
|
||||
Text{"Progressive Magic Powder", "Poudre magique (prog.)", "Medidor de carga progresivo"}};
|
||||
trickNameTable[0x8B] = {
|
||||
Text{"Progressive Memento", "Souvenir (prog.)", "Silbato progresivo"},
|
||||
Text{"Progressive Flute", "Flûte (prog.)", "Flauta progresiva"},
|
||||
Text{"Progressive Recorder", "Harmonica (prog.)", "Armónica progresiva"}};
|
||||
trickNameTable[0xD4] = {
|
||||
Text{"Progressive Titan Blade", "Lame des Titans (prog.)", "Hoja del Titán progresiva"},
|
||||
Text{"Progressive Goron Knife", "Lame Goron (prog.)", "Daga Goron progresiva"},
|
||||
Text{"Progressive Giant Sword", "Épée géante (prog.)", "Espada gigante progresiva"}};
|
||||
|
||||
trickNameTable[0x0F] = {
|
||||
Text{"Magic Bottle", "Flacon magique", "Frasco feérico"},
|
||||
Text{"Glass Bottle", "Flacon de verre", "Botella de cristal"},
|
||||
Text{"Bottle with Water", "Flacon d'eau", "Botella Tingle"}};
|
||||
trickNameTable[0x14] = {
|
||||
Text{"Bottle with Chateau Romani", "Flacon de cuvée Romani", "Botella de Reserva Romani"},
|
||||
Text{"Bottle with Fresh Milk", "Flacon de lait frais", "Botella de leche fresca"},
|
||||
Text{"Bottle with Mystery Milk", "Flacon de lait grand cru", "Botella de leche extra"}};
|
||||
trickNameTable[0x8C] = {
|
||||
Text{"Bottle with Red Chu Jelly", "Flacon de gelée Chuchu rouge", "Jugo de Chuchu Rojo"},
|
||||
Text{"Bottle with Medicine of Life", "Flacon d'élixir rouge", "Botella de medicina de la vida"},
|
||||
Text{"Bottle with Heart Potion", "Flacon de potion de soin", "Botella de poción de salud"}};
|
||||
trickNameTable[0x8D] = {
|
||||
Text{"Bottle with Green Chu Jelly", "Flacon de gelée Chuchu verte", "Jugo de Chuchu Verde"},
|
||||
Text{"Bottle with Medicine of Magic", "Flacon d'élixir vert", "Botella de medicina mágica"},
|
||||
Text{"Bottle with Stamina Potion", "Flacon d'Endurol", "Botella de elixir vigorizante"}};
|
||||
trickNameTable[0x8E] = {
|
||||
Text{"Bottle with Blue Chu Jelly", "Flacon de gelée Chuchu bleue", "Jugo de Chuchu Azul"},
|
||||
Text{"Bottle with Water of Life", "Flacon d'élixir bleu", "Botella de agua de la vida"},
|
||||
Text{"Bottle with Air Potion", "Flacon de potion d'oxygène", "Botella de oxígeno"}};
|
||||
trickNameTable[0x8F] = {
|
||||
Text{"Bottle with Forest Firefly", "Flacon avec une luciole", "Luciérnaga del bosque"},
|
||||
Text{"Bottle with Faerie", "Flacon de poudre féérique", "Gran Hada embotellada"},
|
||||
Text{"Bottle with Stray Fairy", "Flacon avec une fée perdue", "Hada perdida en una botella"}};
|
||||
trickNameTable[0x90] = {
|
||||
Text{"Bottle with Small Jabu-Jabu", "Flacon avec mini Jabu-Jabu", "Lord Chapu-Chapu embotellado"},
|
||||
Text{"Bottle with Hyrule Bass", "Flacon avec perche d'Hyrule", "Locha de Hyrule embotellada"},
|
||||
Text{"Bottle with Hyrule Loach", "Flacon avec loche d'Hyrule", "Perca de Términa embotellada"}};
|
||||
trickNameTable[0x91] = {
|
||||
Text{"Bottle with Will-O-Wisp", "Flacon avec feu follet", "Botella de llama azul"},
|
||||
Text{"Bottle with Ancient Flame", "Flacon de flamme ancienne", "Botella de fuego ancestral"},
|
||||
Text{"Bottle with Nayru's Flame", "Flacon de flamme de Nayru", "Botella de llamas de Nayru"}};
|
||||
trickNameTable[0x92] = {
|
||||
Text{"Bottle with Baby Tektites", "Flacon de bébé Araknon", "Tektites en una botella"},
|
||||
Text{"Bottle with Lanayru Ants", "Flacon de fourmis de Lanelle", "Celestarabajo embotellado"},
|
||||
Text{"Bottle with Insects", "Flacon de bibittes", "Saltabosques embotellados"}};
|
||||
trickNameTable[0x94] = {
|
||||
Text{"Bottle with Ghini", "Flacon avec Ghini", "Ghini en una botella"},
|
||||
Text{"Bottle with Imp Poe", "Flacon avec Spectre", "Espectro en una botella"},
|
||||
Text{"Bottle with Anti-Fairy", "Flacon avec Tetdoss", "Whisp en una botella"}};
|
||||
|
||||
trickNameTable[0x15] = {
|
||||
Text{"Bottle with Maggie's Letter", "Flacon avec lettre de Maggy", "Carta de Dolores"},
|
||||
Text{"Bottle with Letter to Kafei", "Flacon avec lettre pour Kafei", "Carta para Kafei"},
|
||||
Text{"Bottle with Zelda's Letter", "Flacon avec Lettre de Zelda", "Carta náutica"}};
|
||||
trickNameTable[0x93] = {
|
||||
Text{"Bottle with Composer Brother", "Flacon avec un compositeur", "Hermana Poe embotellada"},
|
||||
Text{"Bottle with Jalhalla", "Flacon avec Jalhalla", "Yaihalla embotellado"},
|
||||
Text{"Bottle with Grim Repoe", "Flacon avec le Faucheur", "Bubble en una botella"}};
|
||||
|
||||
trickNameTable[0xC1] = {
|
||||
Text{"Ballad of the Goddess", "Chant de la déesse", "Cántico de la Diosa"},
|
||||
Text{"Song of Healing", "Chant de l'apaisement", "Canción de curación"},
|
||||
Text{"Bolero of Fire", "Boléro du feu", "Bolero del fuego"}};
|
||||
trickNameTable[0xC2] = {
|
||||
Text{"Earth God's Lyric", "Hymne du dieu de la terre", "Melodía del Espíritu de la Tierra"},
|
||||
Text{"Song of Soaring", "Chant de l'envol", "Canción del viento"},
|
||||
Text{"Requiem of Spirit", "Requiem des esprits", "Réquiem del espíritu"}};
|
||||
trickNameTable[0xC3] = {
|
||||
Text{"Wind God's Aria", "Hymne du dieu du vent", "Melodía del Espíritu del Viento"},
|
||||
Text{"Wind's Requiem", "Mélodie du vent", "Melodía del Viento"},
|
||||
Text{"Minuet of Forest", "Menuet de la forêt", "Minueto del bosque"}};
|
||||
trickNameTable[0xC4] = {
|
||||
Text{"Song of Passing", "Mambo de Manbo", "Melodía del transcurrir"},
|
||||
Text{"Command Melody", "Air du marionnettiste", "Cara al Sol"},
|
||||
Text{"Prelude of Light", "Prélude de la lumière", "Preludio de la luz"}};
|
||||
trickNameTable[0xC5] = {
|
||||
Text{"Song of Double Time", "Chant accéléré", "Canción del doble tiempo"},
|
||||
Text{"Inverted Song of Time", "Chant du temps inversé", "Canción del tiempo invertida"},
|
||||
Text{"Serenade of Water", "Sérénade de l'eau", "Serenata del agua"}};
|
||||
trickNameTable[0xC6] = {
|
||||
Text{"Ballad of Gales", "Requiem de la tornade", "Melodía del Tornado"},
|
||||
Text{"Frog's Song of Soul", "Rap des grenouilles", "Canción del alma de la rana"},
|
||||
Text{"Nocturne of Shadow", "Nocturne de l'ombre", "Nocturno de la sombra"}};
|
||||
trickNameTable[0xBB] = {
|
||||
Text{"Saria's Karaoke", "Karaoké de Saria", "Dueto del bosque"},
|
||||
Text{"Sonata of Awakening", "Sonate de l'éveil", "Sonata del despertar"},
|
||||
Text{"Saria's Song", "Chant de Saria", "Canción de Saria"}};
|
||||
trickNameTable[0xBC] = {
|
||||
Text{"Darunia's Tango", "Tango de Darunia", "Coro del fuego"},
|
||||
Text{"Goron Lullaby", "Berceuse des Gorons", "Nana goron"},
|
||||
Text{"Zelda's Lullaby", "Berceuse de Zelda", "Nana de Zelda"}};
|
||||
trickNameTable[0xBD] = {
|
||||
Text{"Ruto's Blues", "Blues de Ruto", "Sonata del agua"},
|
||||
Text{"New Wave Bossa Nova", "Bossa-nova des flots", "Bossanova de las olas"},
|
||||
Text{"Song of Time", "Chant du temps", "Canción del tiempo"}};
|
||||
trickNameTable[0xBE] = {
|
||||
Text{"Nabooru's Reggae", "Reggae de Nabooru", "Reggae del espíritu"},
|
||||
Text{"Elegy of Emptiness", "Hymne du vide", "Elegía al vacío"},
|
||||
Text{"Epona's Song", "Chant d'Épona", "Canción de Epona"}};
|
||||
trickNameTable[0xBF] = {
|
||||
Text{"Impa's Death Metal", "Death métal d'Impa", "Diurno de la sombra"},
|
||||
Text{"Oath to Order", "Ode de l'appel", "Oda al orden"},
|
||||
Text{"Song of Storms", "Chant des tempêtes", "Canción de la tormenta"}};
|
||||
trickNameTable[0xC0] = {
|
||||
Text{"Rauru's Sing-Along", "Chansonnette de Rauru", "Predulio de luz"},
|
||||
Text{"Ballad of the Wind Fish", "Ballade sur Poisson-Rêve", "Balada del Piez Viento"},
|
||||
Text{"Sun's Song", "Chant du soleil", "Canción del Sol"}};
|
||||
|
||||
trickNameTable[0xCB] = {
|
||||
Text{"Pendant of Courage", "Pendentif du courage", "Colgante del valor"},
|
||||
Text{"Farore's Emerald", "Émeraude de Farore", "Esmeralda de Farore"},
|
||||
Text{"Kokiri's Peridot", "Péridot Kokiri", "Ágata de los Kokiri"}};
|
||||
trickNameTable[0xCC] = {
|
||||
Text{"Pendant of Power", "Pendentif de la force", "Colgante del poder"},
|
||||
Text{"Din's Ruby", "Rubis de Din", "Rubí de Din"},
|
||||
Text{"Goron's Garnet", "Grenat Goron", "Topacio de los Goron"}};
|
||||
trickNameTable[0xCD] = {
|
||||
Text{"Pendant of Wisdom", "Pendentif de la sagesse", "Colgante de la sabiduría"},
|
||||
Text{"Nayru's Sapphire", "Saphir de Nayru", "Zafiro de Nayru"},
|
||||
Text{"Zora's Aquamarine", "Aquamarine Zora", "Lapislázuli de los Zora"}};
|
||||
trickNameTable[0xCE] = {
|
||||
Text{"Wind Medallion", "Médaillon du vent", "Medallón del Viento"},
|
||||
Text{"Saria's Medallion", "Médaillon de Saria", "Medallón de Saria"},
|
||||
Text{"Medallion of Forest", "Médaillon du Temple de la Forêt", "Medalla del Bosque"}};
|
||||
trickNameTable[0xCF] = {
|
||||
Text{"Bombos Medallion", "Médaillon des flammes", "Medallón del Temblor"},
|
||||
Text{"Darunia's Medallion", "Médaillon de Darunia", "Medallón de Darunia"},
|
||||
Text{"Medallion of Fire", "Médaillon du Temple du Feu", "Medalla del Fuego"}};
|
||||
trickNameTable[0xD0] = {
|
||||
Text{"Ice Medallion", "Médaillon de glace", "Medallón Helado"},
|
||||
Text{"Ruto's Medallion", "Médaillon de Ruto", "Medallón de Ruto"},
|
||||
Text{"Medallion of Water", "Médaillon du Temple de l'Eau", "Medalla del Agua"}};
|
||||
trickNameTable[0xD1] = {
|
||||
Text{"Quake Medallion", "Médaillon des secousses", "Medallón Llamarada"},
|
||||
Text{"Nabooru's Medallion", "Médaillon de Nabooru", "Medallón de Nabooru"},
|
||||
Text{"Medallion of Spirit", "Médaillon du Temple de l'Esprit", "Medalla del Espíritu"}};
|
||||
trickNameTable[0xD2] = {
|
||||
Text{"Travel Medallion", "Amulette de téléportation", "Medallón Maligno"},
|
||||
Text{"Impa's Medallion", "Médaillon d'Impa", "Medallón de Impa"},
|
||||
Text{"Medallion of Shadow", "Médaillon du Temple de l'Ombre", "Medalla de la Sombra"}};
|
||||
trickNameTable[0xD3] = {
|
||||
Text{"Ether Medallion", "Médaillon d'éther", "Medallón de Tesoro"},
|
||||
Text{"Rauru's Medallion", "Médaillon de Rauru", "Medallón de Rauru"},
|
||||
Text{"Medallion of Light", "Médaillon du temple de lumière", "Medalla de la Luz"}};
|
||||
|
||||
trickNameTable[GI_HEART] = {
|
||||
Text{"Love", "Bisou", "Te amo"},
|
||||
Text{"Heart Container", "Réceptacle de coeur", "Contenedor de corazón"},
|
||||
Text{"Piece of Heart", "Quart de coeur", "Pieza de corazón"}};
|
||||
trickNameTable[GI_RUPEE_GREEN] = {
|
||||
Text{"Green Rupy", "Rupee vert", "Rubia verde"},
|
||||
Text{"One Rupee", "Un rubis", "Guaraní hyliano"},
|
||||
Text{"Rupee (1)", "Rubis (1)", "Peso hyliano"}};
|
||||
trickNameTable[GI_RUPEE_BLUE] = {
|
||||
Text{"Blue Rupy", "Rupee bleu", "Rubia azul"},
|
||||
Text{"Five Rupees", "Cinq rubis", "Bolívar hyliano"},
|
||||
Text{"Rupee (5)", "Rubis (5)", "Peso hyliano"}};
|
||||
trickNameTable[GI_RUPEE_RED] = {
|
||||
Text{"Red Rupy", "Rupee rouge", "Rubia roja"},
|
||||
Text{"Twenty Rupees", "Vingt rubis", "Colon hyliano"},
|
||||
Text{"Rupee (20)", "Rubis (20)", "Peso hyliano"}};
|
||||
trickNameTable[GI_RUPEE_PURPLE] = {
|
||||
Text{"Purple Rupy", "Rupee pourpre", "Rubia morada"},
|
||||
Text{"Fifty Rupees", "Cinquante rubis", "Balboa hyliano"},
|
||||
Text{"Rupee (50)", "Rubis (50)", "Peso hyliano"}};
|
||||
trickNameTable[GI_RUPEE_GOLD] = {
|
||||
Text{"Huge Rupy", "Énorme Rupee", "Rubia gigante"},
|
||||
Text{"Two Hundred Rupees", "Deux cent rubis", "Euro hyliano"},
|
||||
Text{"Rupee (200)", "Rubis (200)", "Dólar hyliano"}};
|
||||
trickNameTable[GI_HEART_PIECE] = {
|
||||
Text{"Piece of Health", "Quart d'énergie", "Pieza de amor"},
|
||||
Text{"Recovery Heart", "Coeur d'énergie", "Corazón"},
|
||||
Text{"Heart Container", "Réceptacle de coeur", "Contenedor de corazón"}};
|
||||
trickNameTable[GI_HEART_CONTAINER_2] = {
|
||||
Text{"Health Container", "Réceptacle d'énergie", "Contenedor de amor"},
|
||||
Text{"Recovery Heart", "Quart de coeur", "Corazón"},
|
||||
Text{"Piece of Heart", "Coeur d'énergie", "Pieza de corazón"}};
|
||||
|
||||
/*
|
||||
//Names for individual upgrades, in case progressive names are replaced
|
||||
trickNameTable[GI_HOOKSHOT] = {
|
||||
Text{"Grappling Hook", "Grappin-griffe", "Gancho lanzable"},
|
||||
Text{"Clawshot", "Lance-chaîne", "Zarpa"},
|
||||
Text{"Gripshot", "Grappince", "Enganchador"}};
|
||||
trickNameTable[GI_LONGSHOT] = {
|
||||
Text{"Longshot, no strings attached", "Grappin sans attrape", "Gancho lanzable más largo"},
|
||||
Text{"Double Clawshot", "Double-grappin", "Superzarpa"},
|
||||
Text{"Switch Hook", "Great grappin", "Gancho chulo"}};
|
||||
trickNameTable[GI_BOMB_BAG_1] = {
|
||||
Text{"Bomb Capacity (20)", "Capacité de bombes (20)", "Bolsa de bombas (contiene 20)"},
|
||||
Text{"Bronze Bomb Bag", "Sac de Bombes de bronze", "Saco de bronce de bombas"},
|
||||
Text{"Small Bomb Bag", "Petit Sac de Bombes", "Zurrón de bombas pequeño"}};
|
||||
trickNameTable[GI_BOMB_BAG_2] = {
|
||||
Text{"Bomb Capacity (30)", "Capacité de bombes (30)", "Bolsa de bombas (contiene 30)"},
|
||||
Text{"Silver Bomb Bag", "Sac de Bombes d'argent", "Saco plateado de bombas"},
|
||||
Text{"Medium Bomb Bag", "Sac de Bombes moyen", "Zurrón de bombas mediano"}};
|
||||
trickNameTable[GI_BOMB_BAG_3] = {
|
||||
Text{"Bomb Capacity (40)", "Capacité de bombes (40)", "Bolsa de bombas (contiene 40)"},
|
||||
Text{"Golden Bomb Bag", "Sac de Bombes d'or", "Saco dorado de bombas"},
|
||||
Text{"Large Bomb Bag", "Gros Sac de Bombes", "Zurrón de bombas grande"}};
|
||||
trickNameTable[GI_BOW_1] = {
|
||||
Text{"Bow", "Arc", "Arco del Hada"},
|
||||
Text{"Hero's Bow", "Arc du héros", "Arco del héroe"},
|
||||
Text{"Small Quiver", "Petit carquois", "Saco de flechas pequeño"}};
|
||||
trickNameTable[GI_BOW_2] = {
|
||||
Text{"Arrow Capacity (40)", "Capacité de flèches (40)", "Capacidad de flechas (40)"},
|
||||
Text{"Silver Quiver", "Carquois d'argent", "Carcaj plateado"},
|
||||
Text{"Medium Quiver", "Carquois moyen", "Saco de flechas mediano"}};
|
||||
trickNameTable[GI_BOW_3] = {
|
||||
Text{"Arrow Capacity (50)", "Capacité de flèches (50)", "Capacidad de flechas (50)"},
|
||||
Text{"Golden Quiver", "Carquois d'or", "Carcaj dorado"},
|
||||
Text{"Large Quiver", "Gros carquois", "Saco de flechas grande"}};
|
||||
trickNameTable[GI_SLINGSHOT_1] = {
|
||||
Text{"Slingshot", "Lance-Pierre", "Tirachinas del Hada"},
|
||||
Text{"Scattershot", "Lance-Pierre rafale", "Tirachinas múltiple"},
|
||||
Text{"Small Seed Satchel", "Petit sac de graines", "Bolsa de semillas pequeña"}};
|
||||
trickNameTable[GI_SLINGSHOT_2] = {
|
||||
Text{"Deku Seed Capacity (40)", "Capacité de graines (40)", "Capacidad de semillas (40)"},
|
||||
Text{"Silver Deku Seed Bullet Bag", "Sac de graines d'argent", "Bolsa de balas (contiene 40)"},
|
||||
Text{"Medium Seed Satchel", "Sac de graines moyen", "Bolsa de semillas mediana"}};
|
||||
trickNameTable[GI_SLINGSHOT_3] = {
|
||||
Text{"Deku Seed Capacity (50)", "Capacité de graines (50)", "Capacidad de semillas (50)"},
|
||||
Text{"Golden Deku Seed Bullet Bag", "Sac de graines d'or", "Bolsa de balas (contiene 50)"},
|
||||
Text{"Large Seed Satchel", "Gros sac de graines", "Bolsa de semillas grande"}};
|
||||
trickNameTable[GI_STRENGTH_1] = {
|
||||
Text{"Goron's Gauntlet", "Gantelet Goron", "Brazalete amarillo"},
|
||||
Text{"Power Bracelet", "Bracelet de force", "Brazalete de fuerza"},
|
||||
Text{"Magic Bracelet", "Bracelet de Lavio", "Brazalete de Ravio"}};
|
||||
trickNameTable[GI_STRENGTH_2] = {
|
||||
Text{"Silver Bracelets", "Bracelets d'argent", "Guantes Moguma"},
|
||||
Text{"Power Gloves", "Gant de puissance", "Guante del Poder"},
|
||||
Text{"Magic Gauntlets", "Gantelet magique", "Guante mágico"}};
|
||||
trickNameTable[GI_STRENGTH_3] = {
|
||||
Text{"Golden Bracelets", "Bracelets d'or", "Guantelete de Thanos"},
|
||||
Text{"Titan's Mitts", "Moufle de titan", "Guantes de Titán"},
|
||||
Text{"Magnetic Gloves", "Magnéto-gants", "Guantes de fuego"}};
|
||||
trickNameTable[GI_SCALE_1] = {
|
||||
Text{"Silver Pearl", "Perle d'argent", "Perla de Plata progresiva"},
|
||||
Text{"Adult Scale", "Écaille d'adulte", "Bola de bolos zora"},
|
||||
Text{"Zora Scale", "Écaille Zora", "Escama de Zora"}};
|
||||
trickNameTable[GI_SCALE_2] = {
|
||||
Text{"Golden Pearl", "Perle d'or", "Perla de Oro progresiva"},
|
||||
Text{"Giant Scale", "Écaille de géant", "Escama de Faren"},
|
||||
Text{"Water Dragon Scale", "Écaille du dragon de l'eau", "Escama de dragón acuático"}};
|
||||
trickNameTable[GI_WALLET_1] = {
|
||||
Text{"Rupee Capacity (200)", "Capacité de rubis (200)", "Capacidad de rupias (200)"},
|
||||
Text{"Silver Wallet", "Bourse d'argent", "Cartera de rupias de adulto"},
|
||||
Text{"Medium Wallet", "Bourse moyenne", "Zurrón de rupias mediano"}};
|
||||
trickNameTable[GI_WALLET_2] = {
|
||||
Text{"Rupee Capacity (500)", "Capacité de rubis (500)", "Capacidad de rupias (500)"},
|
||||
Text{"Golden Wallet", "Bourse d'or", "Cartera de rupias gigante"},
|
||||
Text{"Large Wallet", "Grosse Bourse", "Zurrón de rupias grande"}};
|
||||
trickNameTable[GI_WALLET_3] = {
|
||||
Text{"Rupee Capacity (999)", "Capacité de rubis (999)", "Capacidad de rupias (999)"},
|
||||
Text{"Golden Wallet", "Bourse d'or", "Cartera de ricachón"},
|
||||
Text{"Large Wallet", "Grosse Bourse", "Zurrón de rupias gigante"}};
|
||||
trickNameTable[GI_DEKU_NUT_UPGRADE_1] = {
|
||||
Text{"Deku Bomb Capacity (30)", "Capacité de bombes Mojo (30)", "Capacidad de semillas deku (40)"},
|
||||
Text{"Baba Nut Capacity (30)", "Capacité de noix Baba (30)", "Capacidad de nueces baba (40)"},
|
||||
Text{"Deku Nut Pack (30)", "Paquet de noix Mojo (30)", "Capacidad de nueces mojo (40)"}};
|
||||
trickNameTable[GI_DEKU_NUT_UPGRADE_2] = {
|
||||
Text{"Deku Bomb Capacity (40)", "Capacité de bombes Mojo (40)", "Capacidad de semillas deku (50)"},
|
||||
Text{"Baba Nut Capacity (40)", "Capacité de noix Baba (40)", "Capacidad de nueces baba (50)"},
|
||||
Text{"Deku Nut Pack (40)", "Paquet de noix Mojo (40)", "Capacidad de nueces mojo (50)"}};
|
||||
trickNameTable[GI_DEKU_STICK_UPGRADE_1] = {
|
||||
Text{"Deku Rod Capacity (20)", "Capacité de tiges Mojo (20)", "Capacidad de palos mojo (20)"},
|
||||
Text{"Boko Stick Capacity (20)", "Capacité de Bâtons Boko (20)", "Capacidad de palos boko (20)"},
|
||||
Text{"Deku Stick Pack (20)", "Paquet de bâtons Mojo (20)", "Capacidad de bastones deku (20)"}};
|
||||
trickNameTable[GI_DEKU_STICK_UPGRADE_2] = {
|
||||
Text{"Deku Rod Capacity (30)", "Capacité de tiges Mojo (30)", "Capacidad de palos mojo (30)"},
|
||||
Text{"Boko Stick Capacity (30)", "Capacité de Bâtons Boko (30)", "Capacidad de palos boko (30)"},
|
||||
Text{"Deku Stick Pack (30)", "Paquet de bâtons Mojo (30)", "Capacidad de bastones deku (30)"}};
|
||||
trickNameTable[GI_MAGIC_1] = {
|
||||
Text{"Stamina Meter", "Jauge d'endurance", "Medidor de vigor"},
|
||||
Text{"Energy Meter", "Jauge d'énergie", "Medidor de energía"},
|
||||
Text{"Magic Powder", "Poudre magique", "Medidor de carga"}};
|
||||
trickNameTable[GI_MAGIC_2] = {
|
||||
Text{"Enhanced Stamina Meter", "Jauge d'endurance améliorée", "Medidor de vigor mejorado"},
|
||||
Text{"Enhanced Energy Meter", "Jauge d'énergie améliorée", "Medidor de energía mejorado"},
|
||||
Text{"Enhanced Magic Powder", "Poudre magique améliorée", "Medidor de carga mejorado"}};
|
||||
trickNameTable[GI_OCARINA_1] = {
|
||||
Text{"Ocarina", "Ocarina", "Ocarina"},
|
||||
Text{"Saria's Ocarina", "Ocarina de Saria", "Ocarina de Saria"},
|
||||
Text{"Wood Ocarina", "Ocarina de bois", "Ocarina del Hada"}};
|
||||
trickNameTable[GI_OCARINA_2] = {
|
||||
Text{"Flute", "Flûte", "Flauta"},
|
||||
Text{"Zelda's Ocarina", "Ocarina de Zelda", "Ocarina de Zelda"},
|
||||
Text{"Ocarina of Winds", "Ocarina des vents", "Ocarina del Viento"}};
|
||||
trickNameTable[GI_CUCCO] = {
|
||||
Text{"D.I.Y. Alarm Clock", "Réveille-matin improvisé", "Alarma emplumada"},
|
||||
Text{"Kakariko Cucco", "Cocotte Cocorico", "Cuco de Kakariko"},
|
||||
Text{"Hatched Cucco", "Cocotte éclose", "Pollo"}};
|
||||
trickNameTable[GI_MASK_KEATON] = {
|
||||
Text{"Kee... Something Mask", "Masque de Quiche", "Máscara Kealgo"},
|
||||
Text{"Kitsune Mask", "Masque de Kitsune", "Máscara Kitsune"},
|
||||
Text{"Kafei's Mask", "Masque de Kafei", "Máscara de Kafei"}};
|
||||
trickNameTable[GI_MASK_SKULL] = {
|
||||
Text{"Skull Kid's Mask", "Masque de Skull Kid", "Máscara de Skull Kid"},
|
||||
Text{"Stalfos Mask", "Masque de squelette", "Máscara de Stalfos"},
|
||||
Text{"Captain's Hat", "Heaume du capitaine", "Casco del capitán"}};
|
||||
trickNameTable[GI_MASK_SPOOKY] = {
|
||||
Text{"Skrik Mask", "Masque Skrik", "Máscara Escalofriante"},
|
||||
Text{"ReDead Mask", "Masque de Remort", "Máscara de ReDead"},
|
||||
Text{"Gibdo Mask", "Masque de Gibdo", "Careta de Gibdo"}};
|
||||
trickNameTable[GI_MASK_BUNNY] = {
|
||||
Text{"Peppy Mask", "Masque de Peppy", "Capucha de Pascua"},
|
||||
Text{"Bunny Ears", "Oreilles de lapin", "Orejas de conejo"},
|
||||
Text{"Postman's Hat", "Casquette du facteur", "Gorra de cartero"}};
|
||||
trickNameTable[GI_MASK_GORON] = {
|
||||
Text{"Goro Mask", "Masque Goro", "Máscara Goro"},
|
||||
Text{"Mask of Goron", "Masque des Gorons", "Máscara de los Goron"},
|
||||
Text{"Darunia Mask", "Masque de Darunia", "Máscara de Darmani"}};
|
||||
trickNameTable[GI_MASK_ZORA] = {
|
||||
Text{"Zola Mask", "Masque Zola", "Máscara Zola"},
|
||||
Text{"Mask of Zora", "Masque des Zoras", "Máscara de los Zora"},
|
||||
Text{"Ruto Mask", "Masque de Ruto", "Máscara de Mikau"}};
|
||||
trickNameTable[GI_MASK_GERUDO] = {
|
||||
Text{"Ganguro Mask", "Masque de Ganguro", "Máscara Canguro"},
|
||||
Text{"Mask of Gerudo", "Masque des Gerudos", "Máscara de las Gerudo"},
|
||||
Text{"Nabooru Mask", "Masque de Nabooru", "Máscara de Nabooru"}};
|
||||
trickNameTable[GI_MASK_TRUTH] = {
|
||||
Text{"Sheikah Mask", "Masque Sheikah", "Máscara Sheikah"},
|
||||
Text{"Mask of Gossip", "Masque de potins", "Máscara chismosa"},
|
||||
Text{"Eye of Truth", "oeil de vérité", "Ojo de la Verdad"}};*/
|
||||
}
|
||||
|
||||
//Generate a fake name for the ice trap based on the item it's displayed as
|
||||
Text GetIceTrapName(uint8_t id) {
|
||||
//If the trick names table has not been initialized, do so
|
||||
if (!initTrickNames) {
|
||||
InitTrickNames();
|
||||
initTrickNames = true;
|
||||
}
|
||||
//Randomly get the easy, medium, or hard name for the given item id
|
||||
return RandomElement(trickNameTable[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) {
|
||||
//Kind of hacky, but extract the shop and item position from the name
|
||||
const std::string& name(Location(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;
|
||||
int shopnum = ShopNameToNum[shop];
|
||||
return shopnum*8 + pos;
|
||||
}
|
||||
|
||||
//Without this transformed index, shop-related tables and arrays would need 64 entries- But only half of that is needed for shopsanity
|
||||
//So we use this transformation to map only important indices to an array with 32 entries in the following manner:
|
||||
//Shop index: 4 5 6 7 12 13 14 15 20 21 22 23...
|
||||
//Transformed: 0 1 2 3 4 5 6 7 8 9 10 11...
|
||||
//So we first divide the shop index by 4, then by 2 which basically tells us the index of the shop it's in,
|
||||
//then multiply by 4 since there are 4 items per shop
|
||||
//And finally we use a modulo by 4 to get the index within the "shop" of 4 items, and add
|
||||
int TransformShopIndex(int index) {
|
||||
return 4*((index / 4) / 2) + index % 4;
|
||||
}
|
23
soh/soh/Enhancements/randomizer/3drando/shops.hpp
Normal file
23
soh/soh/Enhancements/randomizer/3drando/shops.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "item.hpp"
|
||||
#include "item_location.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
struct ItemAndPrice {
|
||||
Text Name;
|
||||
int Price;
|
||||
bool Repurchaseable;
|
||||
};
|
||||
|
||||
extern void PlaceVanillaShopItems();
|
||||
extern std::vector<uint32_t> 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 TransformShopIndex(int index);
|
||||
|
||||
extern std::vector<ItemAndPrice> NonShopItems;
|
1479
soh/soh/Enhancements/randomizer/3drando/sound_effects.cpp
Normal file
1479
soh/soh/Enhancements/randomizer/3drando/sound_effects.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user